Skip to content
This repository was archived by the owner on Oct 9, 2022. It is now read-only.

Commit 6688b7b

Browse files
authored
Convert to TypeScript (#36)
1 parent b1b17d0 commit 6688b7b

File tree

307 files changed

+9584
-6992
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

307 files changed

+9584
-6992
lines changed

.babelrc

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
{
22
"presets": [
3-
"env",
4-
"stage-0"
5-
],
6-
"env": {
7-
"test": {
8-
"plugins": [
9-
"babel-plugin-dynamic-import-node"
10-
]
11-
}
12-
}
3+
"@babel/preset-env"
4+
]
135
}

.eslintrc

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
{
2-
"parser": "babel-eslint",
3-
"extends": "vue",
2+
"parser": "vue-eslint-parser",
3+
"env": {
4+
"browser": true
5+
},
6+
"parserOptions": {
7+
"parser": "@typescript-eslint/parser",
8+
"ecmaVersion": 2020
9+
},
10+
"extends": [
11+
"plugin:vue/essential",
12+
"@vue/standard",
13+
"@vue/typescript/recommended"
14+
],
15+
"plugins": [
16+
"@typescript-eslint"
17+
],
418
"globals": {
519
"KOEL_ENV": true,
620
"NODE_ENV": true,
@@ -10,7 +24,17 @@
1024
"rules": {
1125
"camelcase": 0,
1226
"no-multi-str": 0,
13-
"quotes": 0
27+
"no-empty": 0,
28+
"quotes": 0,
29+
"@typescript-eslint/no-var-requires": 0,
30+
"@typescript-eslint/camelcase": 0,
31+
"@typescript-eslint/member-delimiter-style": 0,
32+
"@typescript-eslint/consistent-type-assertions": 0,
33+
"@typescript-eslint/no-inferrable-types": 0,
34+
"@typescript-eslint/no-explicit-any": 0,
35+
"@typescript-eslint/no-non-null-assertion": 0,
36+
"@typescript-eslint/ban-ts-ignore": 0,
37+
"vue/no-side-effects-in-computed-properties": 0,
38+
"vue/valid-v-on": 0
1439
}
1540
}
16-

.travis.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
language: node_js
22
node_js:
3+
- 14
34
- 13
45
- 12
56
- 11
67
- 10
7-
- 8
8-
9-
matrix:
10-
allow_failures:
11-
- node_js: 13
128

139
script: yarn coverage

jest.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
module.exports = {
22
moduleFileExtensions: [
3+
'ts',
34
'js',
45
'vue'
56
],
67
moduleNameMapper: {
78
'^@/(.*)$': '<rootDir>/js/$1'
89
},
910
transform: {
11+
'^.+\\.ts?$': '<rootDir>/node_modules/ts-jest',
1012
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
1113
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
1214
},
@@ -17,7 +19,7 @@ module.exports = {
1719
KOEL_ENV: 'web',
1820
NODE_ENV: 'test'
1921
},
20-
setupTestFrameworkScriptFile: '<rootDir>/js/tests/setup.js',
22+
setupFilesAfterEnv: ['<rootDir>/js/tests/setup.ts'],
2123
verbose: true,
2224
collectCoverage: true,
2325
coverageReporters: ['lcov', 'json', 'html'],

js/app.js

Lines changed: 0 additions & 31 deletions
This file was deleted.

js/app.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference path="./types.d.ts"/>
2+
import './static-loader'
3+
import Vue, { VNode, CreateElement } from 'vue'
4+
import App from './app.vue'
5+
import { http } from './services/index'
6+
7+
if (KOEL_ENV === 'app') {
8+
Vue.use(require('vue-electron'))
9+
}
10+
11+
Vue.config.productionTip = false
12+
13+
/**
14+
* For Ancelot, the ancient cross of war
15+
* for the holy town of Gods
16+
* Gloria, gloria perpetua
17+
* in this dawn of victorya
18+
*/
19+
/* eslint no-new: 0 */
20+
new Vue({
21+
el: '#app',
22+
render: (h: CreateElement): VNode => h(App),
23+
created: (): void => http.init()
24+
})
25+
26+
if (KOEL_ENV !== 'app' && 'serviceWorker' in navigator) {
27+
navigator.serviceWorker.register('./sw.js').then((): void => console.log('Service Worker Registered'))
28+
}

js/app.vue

Lines changed: 39 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@
2020
</div>
2121
</template>
2222

23-
<script>
23+
<script lang="ts">
2424
import Vue from 'vue'
2525
26-
import AppHeader from '@/components/layout/app-header'
27-
import AppFooter from '@/components/layout/app-footer/index'
28-
import EventListeners from '@/components/utils/event-listeners'
29-
import Hotkeys from '@/components/utils/hotkeys'
30-
import LoginForm from '@/components/auth/login-form'
31-
import MainWrapper from '@/components/layout/main-wrapper/index'
32-
import Overlay from '@/components/ui/overlay'
26+
import AppHeader from '@/components/layout/app-header.vue'
27+
import AppFooter from '@/components/layout/app-footer/index.vue'
28+
import EventListeners from '@/components/utils/event-listeners.vue'
29+
import Hotkeys from '@/components/utils/hotkeys.vue'
30+
import LoginForm from '@/components/auth/login-form.vue'
31+
import MainWrapper from '@/components/layout/main-wrapper/index.vue'
32+
import Overlay from '@/components/ui/overlay.vue'
3333
3434
import { event, showOverlay, hideOverlay, $, app as appUtils } from '@/utils'
3535
import { sharedStore, favoriteStore, queueStore, preferenceStore as preferences } from '@/stores'
3636
import { playback, ls, socket, http } from '@/services'
3737
import { clickaway, droppable, focus } from '@/directives'
3838
39-
export default {
39+
export default Vue.extend({
4040
components: {
4141
Hotkeys,
4242
AppHeader,
@@ -45,47 +45,38 @@ export default {
4545
Overlay,
4646
LoginForm,
4747
EventListeners,
48-
SongContextMenu: () => import('@/components/song/context-menu'),
49-
SupportKoel: () => import('@/components/meta/support-koel')
48+
SongContextMenu: () => import('@/components/song/context-menu.vue'),
49+
SupportKoel: () => import('@/components/meta/support-koel.vue')
5050
},
5151
5252
data: () => ({
5353
authenticated: false,
5454
isDesktopApp: KOEL_ENV === 'app',
55-
contextMenuSongs: []
55+
contextMenuSongs: [] as Song[]
5656
}),
5757
58-
async mounted () {
58+
async mounted (): Promise<void> {
5959
// The app has just been initialized, check if we can get the user data with an already existing token
6060
if (ls.get('jwt-token')) {
6161
this.authenticated = true
6262
await this.init()
6363
}
6464
65-
// Create the element to be the ghost drag image.
66-
const dragGhost = document.createElement('div')
67-
dragGhost.id = 'dragGhost'
68-
document.body.appendChild(dragGhost)
69-
70-
// And the textarea to copy stuff
71-
const copyArea = document.createElement('textarea')
72-
copyArea.id = 'copyArea'
73-
document.body.appendChild(copyArea)
74-
7565
// Add an ugly mac/non-mac class for OS-targeting styles.
7666
// I'm crying inside.
7767
$.addClass(document.documentElement, navigator.userAgent.includes('Mac') ? 'mac' : 'non-mac')
7868
},
7969
8070
created () {
81-
event.on(event.$names.CONTEXT_MENU_REQUESTED, (clickEvent, songs) => {
82-
this.contextMenuSongs = [].concat(songs)
83-
this.$nextTick(() => this.$refs.songContextMenu.open(clickEvent.pageY, clickEvent.pageX))
71+
event.on(event.$names.CONTEXT_MENU_REQUESTED, (e: MouseEvent, songs: Song[]): void => {
72+
this.contextMenuSongs = ([] as Song[]).concat(songs)
73+
// @ts-ignore because of .open()
74+
this.$nextTick((): void => this.$refs.songContextMenu.open(e.pageY, e.pageX))
8475
})
8576
},
8677
8778
methods: {
88-
async init () {
79+
async init (): Promise<void> {
8980
showOverlay()
9081
await socket.init()
9182
@@ -100,20 +91,18 @@ export default {
10091
10192
this.requestNotifPermission()
10293
103-
// To confirm or not to confirm closing, it's a question.
104-
window.onbeforeunload = e => {
94+
window.addEventListener('beforeunload', (e: BeforeUnloadEvent): void => {
10595
if (!preferences.confirmClosing) {
10696
return
10797
}
10898
109-
// Notice that a custom message like this has ceased to be supported
110-
// starting from Chrome 51.
111-
return 'You asked Koel to confirm before closing, so here it is.'
112-
}
99+
e.preventDefault()
100+
e.returnValue = ''
101+
})
113102
114103
// Ping the server everytime the window is focused, so that we don't have those
115104
// "suddent" logout.
116-
window.addEventListener('focus', () => http.get('/ping'))
105+
window.addEventListener('focus', (): void => http.get('/ping'))
117106
118107
this.subscribeToBroadcastedEvents()
119108
@@ -129,32 +118,30 @@ export default {
129118
/**
130119
* Request for notification permission if it's not provided and the user is OK with notifs.
131120
*/
132-
requestNotifPermission () {
121+
requestNotifPermission (): void {
133122
if (window.Notification && preferences.notify && window.Notification.permission !== 'granted') {
134-
window.Notification.requestPermission(result => (result === 'denied' && (preferences.notify = false)))
123+
window.Notification.requestPermission().then((result: string): void => {
124+
preferences.notify = result === 'denied'
125+
})
135126
}
136127
},
137128
138-
/**
139-
* When the user logs in, set the whole app to be "authenticated" and initialize it.
140-
*/
141-
onUserLoggedIn () {
129+
onUserLoggedIn (): void {
142130
this.authenticated = true
143131
this.init()
144132
},
145133
146-
/**
147-
* Subscribes to the events broadcasted e.g. from the remote controller.
148-
*/
149-
subscribeToBroadcastedEvents () {
150-
socket.listen(event.$names.SOCKET_TOGGLE_FAVORITE, () => {
151-
queueStore.current && favoriteStore.toggleOne(queueStore.current)
134+
subscribeToBroadcastedEvents (): void {
135+
socket.listen(event.$names.SOCKET_TOGGLE_FAVORITE, (): void => {
136+
if (queueStore.current) {
137+
favoriteStore.toggleOne(queueStore.current)
138+
}
152139
})
153140
},
154141
155-
triggerMaximize: () => appUtils.triggerMaximize()
142+
triggerMaximize: (): void => appUtils.triggerMaximize()
156143
}
157-
}
144+
})
158145
159146
// …and the global directives
160147
Vue.directive('koel-focus', focus)
@@ -166,7 +153,6 @@ Vue.directive('koel-droppable', droppable)
166153
@import "~#/app.scss";
167154
168155
#dragGhost {
169-
position: absolute;
170156
display: inline-block;
171157
background: $colorGreen;
172158
padding: .8rem;
@@ -175,8 +161,10 @@ Vue.directive('koel-droppable', droppable)
175161
font-family: $fontFamily;
176162
font-size: 1rem;
177163
font-weight: $fontWeight_Thin;
178-
top: -100px;
179-
left: 0px;
164+
position: fixed;
165+
top: 0;
166+
left: 0;
167+
z-index: -1;
180168
181169
/**
182170
* We can totally hide this element on touch devices, because there's

0 commit comments

Comments
 (0)