Skip to content

Commit

Permalink
Add simpler handlig & Update eslint rules
Browse files Browse the repository at this point in the history
  • Loading branch information
kadiryazici committed Mar 17, 2024
1 parent 94f57a2 commit ecfae0d
Show file tree
Hide file tree
Showing 35 changed files with 295 additions and 224 deletions.
4 changes: 4 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@ export default antfu({
max: 1,
},
}],
// Require curly always for if statements
'curly': ['error', 'all'],
// if else statements should be separated by a newline
'brace-style': ['error', 'stroustrup', { allowSingleLine: false }],
},
})
83 changes: 80 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { watchEffect } from 'vue'
import { open } from '@tauri-apps/api/shell'
import AppScroller from './components/AppScroller.vue'
import AppSidebar from './components/AppSidebar.vue'
import HomePage from './pages/HomePage.vue'
Expand All @@ -13,23 +14,99 @@ import ContextMenu from './components/ContextMenu.vue'
import { useTheme } from './composables/useTheme'
import { Page, useRoute } from './composables/useRoute'
import { useContextMenu } from './composables/useContextMenu'
import { useAppHooks } from './composables/useAppHooks'
import { isRepository, isThread } from './utils/notification'
import { createGithubWebURL } from './utils/github'
import type { MinimalRepository, Thread } from './api/notifications'
import { markNotificationAsRead, unsubscribeNotification } from './api/notifications'
const store = useStore()
const { currentPage } = useRoute()
const contextmenu = useContextMenu()
useInterval(() => {
if (AppStorage.get('accessToken') && AppStorage.get('user'))
if (AppStorage.get('accessToken') && AppStorage.get('user')) {
store.fetchNotifications()
}
}, FETCH_INTERVAL_DURATION)
const { theme } = useTheme()
watchEffect(() => {
if (theme.value === ColorPreference.Dark)
if (theme.value === ColorPreference.Dark) {
document.documentElement.classList.remove('light-theme')
else
}
else {
document.documentElement.classList.add('light-theme')
}
})
function getThreadsToProcess(target: Thread | MinimalRepository) {
let threads = [] as Thread[]
if (isRepository(target)) {
threads = store.getThreadsOfRepository(target)
}
else if (store.isChecked(target)) {
threads = [...store.checkedItems]
store.checkedItems = []
}
else {
threads = [target]
}
return threads
}
const { onOpen, onUnsubscribe, onMarkAsRead, emitMarkAsRead } = useAppHooks()
onMarkAsRead((target) => {
let threads = [] as Thread[]
if (isRepository(target) || isThread(target)) {
threads = getThreadsToProcess(target)
}
else {
threads = target
}
for (const thread of threads) {
if (!thread.unread) {
continue
}
if (AppStorage.get('showReadNotifications')) {
thread.unread = false
}
else {
store.removeNotificationById(thread.id)
}
markNotificationAsRead(thread.id, AppStorage.get('accessToken')!)
}
})
onOpen((target) => {
const threads = getThreadsToProcess(target)
for (const thread of threads) {
const url = createGithubWebURL({ notification: thread, userId: AppStorage.get('user')!.id })
open(url)
}
if (AppStorage.get('markAsReadOnOpen')) {
emitMarkAsRead(threads)
}
})
onUnsubscribe((target) => {
const threads = getThreadsToProcess(target)
for (const thread of threads) {
unsubscribeNotification(thread.id, AppStorage.get('accessToken')!)
}
emitMarkAsRead(threads)
})
</script>

Expand Down
3 changes: 2 additions & 1 deletion src/api/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ export async function getAccessToken({ clientId, clientSecret, code }: GetAccess
responseType: ResponseType.JSON,
})

if (!res.ok)
if (!res.ok) {
throw res
}

return res
}
7 changes: 4 additions & 3 deletions src/components/AppButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ const props = withDefaults(defineProps<Props>(), {
const emit = defineEmits<Emits>()
defineSlots<{
default: (props: {}) => any
icon: (props: {}) => any
default: (props: Record<string, never>) => any
icon: (props: Record<string, never>) => any
}>()
function handleClick(e: MouseEvent) {
if (props.loading)
if (props.loading) {
return
}
emit('click', e)
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/AppScroller.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ watch(route.currentPage, () => {
focus()
const element = scrollView.value?.osInstance()?.elements().scrollOffsetElement
if (element)
if (element) {
element.scrollTop = 0
}
}, { flush: 'post' })
const { theme } = useTheme()
Expand Down
9 changes: 8 additions & 1 deletion src/components/AppSidebar.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { open } from '@tauri-apps/api/shell'
import { exit } from '@tauri-apps/api/process'
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { REPO_LINK } from '../constants'
import { useStore } from '../stores/store'
import { AppStorage } from '../storage'
Expand Down Expand Up @@ -50,6 +50,12 @@ const moreItems = computed(() => [
useKey('r', () => {
store.fetchNotifications(true)
}, { source: () => route.currentPage.value === Page.Home })
const morePopover = ref<InstanceType<typeof Popover> | null>(null)
useKey('.', () => {
morePopover.value?.show()
})
</script>

<template>
Expand Down Expand Up @@ -140,6 +146,7 @@ useKey('r', () => {
/>

<Popover
ref="morePopover"
:target="el"
:wowerlayOptions="{ position: 'right-end' }"
>
Expand Down
3 changes: 2 additions & 1 deletion src/components/MenuItems.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ function setupHandle(ctx: Context) {
const popoverContext = usePopoverContext()
ctx.onSelect((meta, item) => {
if (popoverContext)
if (popoverContext) {
popoverContext.visible.value = false
}
})
onMounted(() => {
Expand Down
10 changes: 6 additions & 4 deletions src/components/NotificationItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Props = {
type Emits = {
(e: 'click:notification', notification: Thread): void
(e: 'click:repo', repoFullName: string): void
(e: 'click:repo', repo: MinimalRepository): void
(e: 'update:checked', value: boolean): void
(e: 'contextmenu', value: Thread, event: MouseEvent): void
}
Expand All @@ -33,8 +33,9 @@ function isInteractedCheckbox(e: MouseEvent | KeyboardEvent) {
}
function handleThreadClick(thread: Thread, event: MouseEvent | KeyboardEvent) {
if ((event instanceof KeyboardEvent && event.repeat))
if ((event instanceof KeyboardEvent && event.repeat)) {
return
}
if (props.checkable && ((event.ctrlKey || event.metaKey) || isInteractedCheckbox(event))) {
emit('update:checked', !props.checked)
Expand All @@ -45,8 +46,9 @@ function handleThreadClick(thread: Thread, event: MouseEvent | KeyboardEvent) {
}
function handleRepoClick(repo: MinimalRepository, event: MouseEvent | KeyboardEvent) {
if ((event instanceof KeyboardEvent && event.repeat))
if ((event instanceof KeyboardEvent && event.repeat)) {
return
}
if (props.checkable && ((event.ctrlKey || event.metaKey) || isInteractedCheckbox(event))) {
if (props.indeterminate) {
Expand All @@ -58,7 +60,7 @@ function handleRepoClick(repo: MinimalRepository, event: MouseEvent | KeyboardEv
return
}
emit('click:repo', repo.full_name)
emit('click:repo', repo)
}
</script>

Expand Down
3 changes: 2 additions & 1 deletion src/components/Popover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ const handleTransition: WowerlayTransitionFn = (type, { popover }, done) => {
})
animation.onfinish = () => {
if (type === 'enter')
if (type === 'enter') {
popover.style.transformOrigin = oldTransformOrigin
}
done()
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/Tooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ useEventListener(targetGetter, 'mouseenter', handleTargetInteractionStart)
useEventListener(targetGetter, 'mouseleave', handleTargetInteractionEnd)
useEventListener(targetGetter, 'blur', handleTargetInteractionEnd)
useEventListener(targetGetter, 'focus', (e) => {
if (!(e.target instanceof HTMLElement) || !e.target.hasAttribute('data-focus-visible-added'))
if (!(e.target instanceof HTMLElement) || !e.target.hasAttribute('data-focus-visible-added')) {
return
}
handleTargetInteractionStart()
})
Expand Down
21 changes: 21 additions & 0 deletions src/composables/useAppHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { MinimalRepository, Thread } from '../api/notifications'
import { singleton } from '../utils/common'
import { useCustomHook } from './useCustomHook'

export const useAppHooks = singleton(() => {
const [onMarkAsRead, emitMarkAsRead] = useCustomHook<[target: MinimalRepository | Thread | Thread[]]>()
const [onOpen, emitOpen] = useCustomHook<[target: MinimalRepository | Thread]>()
const [onRefetch, emitRefetch] = useCustomHook()
const [onUnsubscribe, emitUnsubscribe] = useCustomHook<[target: MinimalRepository | Thread]>()

return {
onMarkAsRead,
emitMarkAsRead,
onOpen,
emitOpen,
onRefetch,
emitRefetch,
onUnsubscribe,
emitUnsubscribe,
}
})
9 changes: 6 additions & 3 deletions src/composables/useCustomHook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ export function useCustomHook<const T extends readonly unknown[] = []>() {
})

function emit(...args: T) {
if (disposed)
if (disposed) {
return
}

for (const hook of hooks)
for (const hook of hooks) {
hook(...args)
}
}

function on(hook: (...args: T) => void) {
if (disposed)
if (disposed) {
return () => {}
}

hooks.add(hook)
tryOnScopeDispose(() => hooks.delete(hook))
Expand Down
6 changes: 4 additions & 2 deletions src/composables/useElementNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ export function useElementNavigation({
function focusItemInDirection(navigation: Navigation) {
let currentIndex = getFocusedItemIndex(elements.value, targetQuery)

if (navigation === Navigation.Next && currentIndex < elements.value.length - 1)
if (navigation === Navigation.Next && currentIndex < elements.value.length - 1) {
currentIndex++
else if (navigation === Navigation.Previous && currentIndex > 0)
}
else if (navigation === Navigation.Previous && currentIndex > 0) {
currentIndex--
}

const element = elements.value[currentIndex]
element.focus()
Expand Down
2 changes: 1 addition & 1 deletion src/composables/useI18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type Locale = 'en' | 'tr'
const en = {
navigateToRepository: 'Navigate to repository',
reloadNotifications: (shortcut: string) => `Reload notifications (${shortcut})`,
more: 'More',
more: 'More ( . )',
changelog: 'Changelog',
aNewVersionIsAvailable: 'A new version is available!',
settings: 'Settings',
Expand Down
3 changes: 2 additions & 1 deletion src/composables/useInterval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { getCurrentScope, onScopeDispose } from 'vue'
export function useInterval(callback: () => void, duration: number) {
const interval = setInterval(callback, duration)

if (getCurrentScope())
if (getCurrentScope()) {
onScopeDispose(() => clearInterval(interval))
}

return () => {
clearInterval(interval)
Expand Down
Loading

0 comments on commit ecfae0d

Please sign in to comment.