Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: Talk Desktop Settings #792

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/talk/renderer/Settings/components/AccountsSettingsSection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!--
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<script setup lang="ts">
import { t } from '@nextcloud/l10n'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
import IconAccountMultiplePlus from 'vue-material-design-icons/AccountMultiplePlus.vue'
import IconDelete from 'vue-material-design-icons/Delete.vue'
import SettingsSubsection from './SettingsSubsection.vue'
</script>

<template>
<SettingsSubsection>
<ul>
<NcListItem name="Grigorii K. Shartsev" details="nextcloud.local">
<template #icon>
<NcAvatar user="shgkme" />
</template>
<template #subname>
[email protected]
</template>
<template #actions>
<NcActionButton>
<template #icon>
<IconDelete :size="20" />
</template>
{{ t('talk_desktop', 'Remove') }}
</NcActionButton>
</template>
</NcListItem>
<NcListItem name="admin" details="stable30.local">
<template #icon>
<NcAvatar user="admin" />
</template>
<template #subname>
[email protected]
</template>
<template #actions>
<NcActionButton>
<template #icon>
<IconDelete :size="20" />
</template>
{{ t('talk_desktop', 'Remove') }}
</NcActionButton>
</template>
</NcListItem>
</ul>
<NcButton wide>
<template #icon>
<IconAccountMultiplePlus :size="20" />
</template>
{{ t('talk_desktop', 'Log into a new account') }}
</NcButton>
</SettingsSubsection>
</template>
107 changes: 107 additions & 0 deletions src/talk/renderer/Settings/components/DesktopSettingsSection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<!--
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<script setup lang="ts">
import { t } from '@nextcloud/l10n'
import { computed, type ComputedRef, type Ref, ref, watch } from 'vue'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'
import SettingsSubsection from './SettingsSubsection.vue'
import IconThemeLightDark from 'vue-material-design-icons/ThemeLightDark.vue'
import IconWeatherSunny from 'vue-material-design-icons/WeatherSunny.vue'

Check failure on line 13 in src/talk/renderer/Settings/components/DesktopSettingsSection.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'IconWeatherSunny' is defined but never used
import IconWeatherNight from 'vue-material-design-icons/WeatherNight.vue'

Check failure on line 14 in src/talk/renderer/Settings/components/DesktopSettingsSection.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'IconWeatherNight' is defined but never used
import IconBellOutline from 'vue-material-design-icons/BellOutline.vue'
import { applyBodyThemeAttrs } from '../../../../shared/theme.utils.js'

type Theme = 'default' | 'light' | 'dark'
type SelectOption<T> = { label: string, value: T }

// Just an example
const theme: Ref<Theme> = ref('default')
watch(theme, () => {
applyBodyThemeAttrs(theme.value)
})
const themeOptions = [
{ label: t('talk_desktop', 'System default'), value: 'default' },
{ label: t('talk_desktop', 'Light'), value: 'light' },
{ label: t('talk_desktop', 'Dark'), value: 'dark' },
] as const
const themeOption: ComputedRef<SelectOption<Theme>> = computed({

Check failure on line 31 in src/talk/renderer/Settings/components/DesktopSettingsSection.vue

View workflow job for this annotation

GitHub Actions / NPM typecheck

No overload matches this call.
get: () => themeOptions.find(option => option.value === theme.value),

set: (valueOption: { label: string, value: Theme }) => {
theme.value = valueOption.value
},
})

const playSound = ref('no-dnd')
const playSoundOptions = [
{ label: t('talk_desktop', 'Always'), value: 'always' },
{ label: t('talk_desktop', 'When not in Do Not Disturb'), value: 'no-dnd' },
{ label: t('talk_desktop', 'Never'), value: 'never' },
] as const
const playSoundOption = computed({

Check failure on line 45 in src/talk/renderer/Settings/components/DesktopSettingsSection.vue

View workflow job for this annotation

GitHub Actions / NPM typecheck

No overload matches this call.
get: () => playSoundOptions.find(option => option.value === playSound.value),

set: (valueOption: { value: string }) => {
playSound.value = valueOption.value
},
})

const runMinimizedToTray = ref(false)
</script>

<template>
<div>
<SettingsSubsection :name="t('talk_desktop', 'General')">
<NcCheckboxRadioSwitch :checked.sync="runMinimizedToTray" type="switch">
{{ t('talk_desktop', 'Launch at startup') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :checked.sync="runMinimizedToTray" type="switch">
{{ t('talk_desktop', 'Launch minimized to the system tray') }}
</NcCheckboxRadioSwitch>
</SettingsSubsection>

<SettingsSubsection :name="t('talk_desktop', 'Appearance')">
<label style="display: flex; gap: 8px; padding: 0 8px;">
<span style="display: flex; align-items: center">
<IconThemeLightDark :size="20" style="width: 36px" />
<span>{{ t('talk_desktop', 'Theme') }}</span>
</span>
<NcSelect v-model="themeOption"
:clearable="false"
:searchable="false"
label-outside
style="margin: 0 !important; flex: 1 0 auto;"
:options="themeOptions" />
</label>

<NcCheckboxRadioSwitch :checked.sync="runMinimizedToTray" type="switch">
{{ t('talk_desktop', 'Use monochrome tray icon') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :checked.sync="runMinimizedToTray" type="switch">
{{ t('talk_desktop', 'Use system title bar') }}
</NcCheckboxRadioSwitch>
</SettingsSubsection>

<SettingsSubsection :name="t('talk_desktop', 'Notifications')">
<label style="display: flex; gap: 8px; padding: 0 8px;">
<span style="display: flex; align-items: center">
<IconBellOutline :size="20" style="width: 36px" />
<span>{{ t('talk_desktop', 'Notification sound') }}</span>
</span>
<NcSelect v-model="playSoundOption"
:clearable="false"
:searchable="false"
label-outside
style="margin: 0 !important"
:options="playSoundOptions" />
</label>
<NcCheckboxRadioSwitch :checked.sync="runMinimizedToTray" type="switch">
{{ t('talk_desktop', 'Show message text in the notification') }}
</NcCheckboxRadioSwitch>
</SettingsSubsection>
</div>
</template>
35 changes: 35 additions & 0 deletions src/talk/renderer/Settings/components/SettingsSubsection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!--
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<script setup lang="ts">
defineProps<{
name?: string
}>()
</script>

<template>
<div class="settings-subsection">
<h3 v-if="name" class="settings-subsection__title">
{{ name }}
</h3>
<div class="setting-subsection__content">
<slot />
</div>
</div>
</template>

<style scoped>
.settings-subsection__title {
/* Override the default margin */
margin-block-start: 0 !important;
}

.setting-subsection__content {
display: flex;
flex-direction: column;
gap: var(--default-grid-baseline);
align-items: stretch;
}
</style>
43 changes: 43 additions & 0 deletions src/talk/renderer/Settings/createSettingsSectionElement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import Vue from 'vue'
import type { DefineComponent, Component, ComponentInstance } from 'vue'

/**
* Create a custom element for a settings section from a Vue component
* @param component - Vue component to use as a settings section
*/
export function createSettingsSectionElement(component: Component): CustomElementConstructor & { tagName: string } {
class SettingsSectionElement extends HTMLElement {

static tagName = 'talk-desktop-settings-section-' + Math.random().toString(36).substring(6)

vm: ComponentInstance
rootElement: HTMLElement
isMounted: boolean = false

constructor() {
super()
this.rootElement = document.createElement('div')
const ComponentConstructor = Vue.extend(component as DefineComponent)
this.vm = new ComponentConstructor()
}

connectedCallback() {
if (this.isMounted) {
return
}
this.isMounted = true
this.appendChild(this.rootElement)
this.vm.$mount(this.rootElement)
}

}

window.customElements.define(SettingsSectionElement.tagName, SettingsSectionElement)

return SettingsSectionElement
}
26 changes: 26 additions & 0 deletions src/talk/renderer/Settings/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { t } from '@nextcloud/l10n'
import { createSettingsSectionElement } from './createSettingsSectionElement.ts'
import DesktopSettingsSection from './components/DesktopSettingsSection.vue'
import AccountsSettingsSection from './components/AccountsSettingsSection.vue'

/**
* Register Talk Desktop settings sections
*/
export function registerTalkDesktopSettingsSection() {
window.OCA.Talk.Settings.registerSection({
id: 'talk-desktop-settings',
name: t('talk_desktop', 'Application'),
element: createSettingsSectionElement(DesktopSettingsSection).tagName,
})

window.OCA.Talk.Settings.registerSection({
id: 'talk-desktop-accounts',
name: t('talk_desktop', 'Accounts'),
element: createSettingsSectionElement(AccountsSettingsSection).tagName,
})
}
8 changes: 8 additions & 0 deletions src/talk/renderer/components/MainMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<script setup>
import { computed } from 'vue'

import IconCog from 'vue-material-design-icons/Cog.vue'
import IconReload from 'vue-material-design-icons/Reload.vue'
import IconWeb from 'vue-material-design-icons/Web.vue'
import IconBug from 'vue-material-design-icons/Bug.vue'
Expand All @@ -25,6 +26,7 @@ const talkRouter = window.OCA.Talk.Desktop.talkRouter
const talkWebLink = computed(() => generateUrl(talkRouter.value?.currentRoute?.fullPath ?? ''))
const showHelp = () => window.TALK_DESKTOP.showHelp()
const reload = () => window.location.reload()
const openSettings = () => window.OCA.Talk.Settings.open()
</script>

<template>
Expand Down Expand Up @@ -59,6 +61,12 @@ const reload = () => window.location.reload()

<NcActionSeparator />

<NcActionButton close-after-click @click="openSettings">
<template #icon>
<IconCog :size="20" />
</template>
{{ t('talk_desktop', 'Settings') }}
</NcActionButton>
<NcActionButton @click="showHelp">
<template #icon>
<IconInformationOutline :size="20" />
Expand Down
3 changes: 3 additions & 0 deletions src/talk/renderer/talk.main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { setupWebPage } from '../../shared/setupWebPage.js'
import { createViewer } from './Viewer/Viewer.js'
import { createDesktopApp } from './desktop.app.js'
import { registerTalkDesktopSettingsSection } from './Settings/index.ts'

// Initially open the welcome page, if not specified
if (!window.location.hash) {
Expand All @@ -36,4 +37,6 @@ initTalkHashIntegration(window.OCA.Talk.instance)

window.OCA.Talk.Desktop.talkRouter.value = window.OCA.Talk.instance.$router

registerTalkDesktopSettingsSection()

await import('./notifications/notifications.store.js')
Loading