Merge pull request #3336 from h3poteto/iss-3301/preferences

refs #3301 Rewrite Preferences with composition API
This commit is contained in:
AkiraFukushima 2022-05-07 15:18:10 +09:00 committed by GitHub
commit 70027f9e27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 658 additions and 627 deletions

View File

@ -12,6 +12,7 @@ export type LanguageList = {
ja: LanguageType
ko: LanguageType
pl: LanguageType
id: LanguageType
it: LanguageType
zh_cn: LanguageType
zh_tw: LanguageType

View File

@ -54,26 +54,34 @@
</el-container>
</template>
<script>
import { mapState } from 'vuex'
<script lang="ts">
import { defineComponent, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useStore } from '@/store'
export default {
export default defineComponent({
name: 'preferences',
computed: {
...mapState({
primaryColor: state => state.App.theme.primary_color,
backgroundColor: state => state.App.theme.background_color
})
},
methods: {
close() {
this.$router.push({ path: '/', query: { redirect: 'home' } })
},
activeRoute() {
return this.$route.path
setup() {
const store = useStore()
const router = useRouter()
const route = useRoute()
const primaryColor = computed(() => store.state.App.theme.primary_color)
const backgroundColor = computed(() => store.state.App.theme.background_color)
const close = () => {
router.push({ path: '/', query: { redirect: 'home' } })
}
const activeRoute = () => route.path
return {
primaryColor,
backgroundColor,
close,
activeRoute
}
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -39,89 +39,103 @@
</el-table>
</el-form-item>
<el-form-item>
<el-popover placement="top" width="160" v-model="deletePopoverVisible">
<p>{{ $t('preferences.account.confirm_message') }}</p>
<div style="text-align: right; margin: 0">
<el-button size="small" type="text" @click="deletePopoverVisible = false">{{ $t('preferences.account.cancel') }}</el-button>
<el-button type="danger" size="small" @click="removeAllAssociations">{{ $t('preferences.account.confirm') }}</el-button>
</div>
<el-popconfirm
:confirm-button-text="$t('preferences.account.confirm')"
:cancel-button-text="$t('preferences.account.cancel')"
:title="$t('preferences.account.confirm_message')"
@confirm="removeAllAssociations"
>
<template #reference>
<el-button type="danger">{{ $t('preferences.account.remove_all_associations') }}</el-button>
</template>
</el-popover>
</el-popconfirm>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { mapState } from 'vuex'
<script lang="ts">
import { defineComponent, computed, onMounted } from 'vue'
import { useI18next } from 'vue3-i18next'
import { useRouter } from 'vue-router'
import { useStore } from '@/store'
import { ACTION_TYPES, MUTATION_TYPES } from '@/store/Preferences/Account'
import { ElMessage } from 'element-plus'
import { LocalAccount } from '~/src/types/localAccount'
export default {
data() {
return {
openRemoveDialog: false,
deletePopoverVisible: false
}
},
export default defineComponent({
name: 'account',
computed: {
...mapState({
accounts: state => state.Preferences.Account.accounts,
accountLoading: state => state.Preferences.Account.accountLoading
}),
...mapState({
backgroundColor: state => state.App.theme.background_color
setup() {
const space = 'Preferences/Account'
const store = useStore()
const i18n = useI18next()
const router = useRouter()
const accounts = computed(() => store.state.Preferences.Account.accounts)
const accountLoading = computed(() => store.state.Preferences.Account.accountLoading)
const backgroundColor = computed(() => store.state.App.theme.background_color)
onMounted(() => {
loadAccounts()
})
},
created() {
this.loadAccounts()
},
methods: {
async loadAccounts() {
this.$store.commit('Preferences/Account/updateAccountLoading', true)
const loadAccounts = async () => {
store.commit(`${space}/${MUTATION_TYPES.UPDATE_ACCOUNT_LOADING}`, true)
try {
await this.$store.dispatch('Preferences/Account/loadAccounts')
await store.dispatch(`${space}/${ACTION_TYPES.LOAD_ACCOUNTS}`)
} catch (err) {
return this.$message({
message: this.$t('message.account_load_error'),
ElMessage({
message: i18n.t('message.account_load_error'),
type: 'error'
})
} finally {
this.$store.commit('Preferences/Account/updateAccountLoading', false)
store.commit(`${space}/${MUTATION_TYPES.UPDATE_ACCOUNT_LOADING}`, false)
}
},
removeAccount(index, accounts) {
this.$store
.dispatch('Preferences/Account/removeAccount', accounts[index])
}
const removeAccount = (index: number, accounts: Array<LocalAccount>) => {
store
.dispatch(`${space}/${ACTION_TYPES.REMOVE_ACCOUNT}`, accounts[index])
.then(() => {
this.loadAccounts()
loadAccounts()
})
.catch(() => {
this.$message({
message: this.$t('message.account_remove_error'),
ElMessage({
message: i18n.t('message.account_remove_error'),
type: 'error'
})
})
},
forward(index, accounts) {
this.$store.dispatch('Preferences/Account/forwardAccount', accounts[index]).then(() => {
this.loadAccounts()
})
},
backward(index, accounts) {
this.$store.dispatch('Preferences/Account/backwardAccount', accounts[index]).then(() => {
this.loadAccounts()
})
},
removeAllAssociations() {
this.deletePopoverVisible = false
this.$store.dispatch('Preferences/Account/removeAllAccounts').then(() => {
this.$router.push('/login')
}
const forward = (index: number, accounts: Array<LocalAccount>) => {
store.dispatch(`${space}/${ACTION_TYPES.FORWARD_ACCOUNT}`, accounts[index]).then(() => {
loadAccounts()
})
}
const backward = (index: number, accounts: Array<LocalAccount>) => {
store.dispatch(`${space}/${ACTION_TYPES.BACKWARD_ACCOUNT}`, accounts[index]).then(() => {
loadAccounts()
})
}
const removeAllAssociations = () => {
store.dispatch(`${space}/${ACTION_TYPES.REMOVE_ALL_ACCOUNTS}`).then(() => {
router.push('/login')
})
}
return {
accounts,
accountLoading,
backgroundColor,
removeAccount,
forward,
backward,
removeAllAssociations
}
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -48,82 +48,79 @@
</div>
</template>
<script>
import { mapState } from 'vuex'
import Toot from './Appearance/Toot'
import ColorPallet from './Appearance/ColorPallet'
<script lang="ts">
import { defineComponent, computed, onMounted } from 'vue'
import { useStore } from '@/store'
import Toot from './Appearance/Toot.vue'
import ColorPallet from './Appearance/ColorPallet.vue'
import DisplayStyle from '~/src/constants/displayStyle'
import Theme from '~/src/constants/theme'
import TimeFormat from '~/src/constants/timeFormat'
import { ACTION_TYPES } from '@/store/Preferences/Appearance'
export default {
export default defineComponent({
name: 'appearance',
components: {
Toot,
ColorPallet
},
data() {
setup() {
const space = 'Preferences/Appearance'
const store = useStore()
const nameStyles = [DisplayStyle.DisplayNameAndUsername, DisplayStyle.DisplayName, DisplayStyle.Username]
const themes = [Theme.System, Theme.Light, Theme.Dark, Theme.SolarizedLight, Theme.SolarizedDark, Theme.KimbieDark, Theme.Custom]
const timeFormats = [TimeFormat.Absolute, TimeFormat.Relative]
const fontSize = computed(() => store.state.Preferences.Appearance.appearance.fontSize)
const fontList = computed(() => store.state.Preferences.Appearance.fonts)
const tootPadding = computed(() => store.state.Preferences.Appearance.appearance.tootPadding)
const theme = computed({
get: () => store.state.Preferences.Appearance.appearance.theme,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_THEME}`, value)
})
const displayNameStyle = computed({
get: () => store.state.Preferences.Appearance.appearance.displayNameStyle,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_DISPLAY_NAME_STYLE}`, value)
})
const timeFormat = computed({
get: () => store.state.Preferences.Appearance.appearance.timeFormat,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_TIME_FORMAT}`, value)
})
const customizeThemeColor = computed(() => theme.value === Theme.Custom.key)
const font = computed({
get: () => store.state.Preferences.Appearance.appearance.font,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_FONT}`, value)
})
onMounted(() => {
store.dispatch(`${space}/${ACTION_TYPES.LOAD_APPEARANCE}`)
store.dispatch(`${space}/${ACTION_TYPES.LOAD_FONTS}`)
})
const updateFontSize = async (value: number) => {
await store.dispatch(`${space}/${ACTION_TYPES.UPDATE_FONT_SIZE}`, value)
}
const updateTootPadding = async (value: number) => {
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_TOOT_PADDING}`, value)
}
return {
nameStyles: [DisplayStyle.DisplayNameAndUsername, DisplayStyle.DisplayName, DisplayStyle.Username],
themes: [Theme.System, Theme.Light, Theme.Dark, Theme.SolarizedLight, Theme.SolarizedDark, Theme.KimbieDark, Theme.Custom],
timeFormats: [TimeFormat.Absolute, TimeFormat.Relative]
}
},
computed: {
...mapState('Preferences/Appearance', {
fontSize: state => state.appearance.fontSize,
fontList: state => state.fonts,
tootPadding: state => state.appearance.tootPadding
}),
theme: {
get() {
return this.$store.state.Preferences.Appearance.appearance.theme
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateTheme', value)
}
},
displayNameStyle: {
get() {
return this.$store.state.Preferences.Appearance.appearance.displayNameStyle
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateDisplayNameStyle', value)
}
},
timeFormat: {
get() {
return this.$store.state.Preferences.Appearance.appearance.timeFormat
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateTimeFormat', value)
}
},
customizeThemeColor() {
return this.theme === Theme.Custom.key
},
font: {
get() {
return this.$store.state.Preferences.Appearance.appearance.font
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateFont', value)
}
}
},
created() {
this.$store.dispatch('Preferences/Appearance/loadAppearance')
this.$store.dispatch('Preferences/Appearance/loadFonts')
},
methods: {
async updateFontSize(value) {
await this.$store.dispatch('Preferences/Appearance/updateFontSize', value)
},
async updateTootPadding(value) {
await this.$store.dispatch('Preferences/Appearance/updateTootPadding', value)
nameStyles,
themes,
timeFormats,
fontSize,
fontList,
tootPadding,
theme,
displayNameStyle,
timeFormat,
customizeThemeColor,
font,
updateFontSize,
updateTootPadding
}
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -1,189 +1,144 @@
<template>
<el-form class="pallet" label-position="top" size="small">
<div class="item">
<el-form-item
:label="$t('preferences.appearance.custom_theme.background_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.background_color')">
<el-color-picker v-model="background"></el-color-picker>
</el-form-item>
<el-form-item
:label="
$t('preferences.appearance.custom_theme.selected_background_color')
"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.selected_background_color')">
<el-color-picker v-model="selectedBackground"></el-color-picker>
</el-form-item>
</div>
<div class="item">
<el-form-item
:label="$t('preferences.appearance.custom_theme.global_header_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.global_header_color')">
<el-color-picker v-model="globalHeader"></el-color-picker>
</el-form-item>
<el-form-item
:label="$t('preferences.appearance.custom_theme.side_menu_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.side_menu_color')">
<el-color-picker v-model="sideMenu"></el-color-picker>
</el-form-item>
</div>
<div class="item">
<el-form-item
:label="$t('preferences.appearance.custom_theme.primary_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.primary_color')">
<el-color-picker v-model="primary"></el-color-picker>
</el-form-item>
<el-form-item
:label="$t('preferences.appearance.custom_theme.regular_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.regular_color')">
<el-color-picker v-model="regular"></el-color-picker>
</el-form-item>
</div>
<div class="item">
<el-form-item
:label="$t('preferences.appearance.custom_theme.secondary_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.secondary_color')">
<el-color-picker v-model="secondary"></el-color-picker>
</el-form-item>
<el-form-item
:label="$t('preferences.appearance.custom_theme.border_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.border_color')">
<el-color-picker v-model="border"></el-color-picker>
</el-form-item>
</div>
<div class="item">
<el-form-item
:label="$t('preferences.appearance.custom_theme.header_menu_color')"
>
<el-form-item :label="$t('preferences.appearance.custom_theme.header_menu_color')">
<el-color-picker v-model="headerMenu"></el-color-picker>
</el-form-item>
<el-form-item
:label="$t('preferences.appearance.custom_theme.wrapper_mask_color')"
>
<el-color-picker
v-model="wrapperMask"
:show-alpha="true"
></el-color-picker>
<el-form-item :label="$t('preferences.appearance.custom_theme.wrapper_mask_color')">
<el-color-picker v-model="wrapperMask" :show-alpha="true"></el-color-picker>
</el-form-item>
</div>
</el-form>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent, computed } from 'vue'
import { useStore } from '@/store'
import { ACTION_TYPES } from '@/store/Preferences/Appearance'
export default defineComponent({
name: 'color-pallet',
computed: {
background: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.background_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
background_color: value,
setup() {
const space = 'Preferences/Appearance'
const store = useStore()
const background = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.background_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
background_color: value
})
},
},
selectedBackground: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.selected_background_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
selected_background_color: value,
})
const selectedBackground = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.selected_background_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
selected_background_color: value
})
},
},
globalHeader: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.global_header_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
global_header_color: value,
})
const globalHeader = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.global_header_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
global_header_color: value
})
},
},
sideMenu: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.side_menu_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
side_menu_color: value,
})
const sideMenu = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.side_menu_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
side_menu_color: value
})
},
},
primary: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.primary_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
primary_color: value,
})
const primary = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.primary_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
primary_color: value
})
},
},
regular: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.regular_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
regular_color: value,
})
const regular = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.regular_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
regular_color: value
})
},
},
secondary: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.secondary_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
secondary_color: value,
})
const secondary = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.secondary_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
secondary_color: value
})
},
},
border: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.border_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
border_color: value,
})
const border = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.border_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
border_color: value
})
},
},
headerMenu: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.header_menu_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
header_menu_color: value,
})
const headerMenu = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.header_menu_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
header_menu_color: value
})
},
},
wrapperMask: {
get() {
return this.$store.state.Preferences.Appearance.appearance
.customThemeColor.wrapper_mask_color
},
set(value) {
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
wrapper_mask_color: value,
})
const wrapperMask = computed({
get: () => store.state.Preferences.Appearance.appearance.customThemeColor.wrapper_mask_color,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR}`, {
wrapper_mask_color: value
})
},
},
},
}
})
return {
background,
selectedBackground,
globalHeader,
sideMenu,
primary,
regular,
secondary,
border,
headerMenu,
wrapperMask
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -1,5 +1,5 @@
<template>
<div class="status" tabIndex="0" ref="status">
<div class="status" tabIndex="0" ref="statusRef">
<div class="toot">
<div class="icon">
<img :src="sampleIcon" />
@ -44,12 +44,13 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent, computed, toRefs } from 'vue'
import moment from 'moment'
import DisplayStyle from '~/src/constants/displayStyle'
import TimeFormat from '~/src/constants/timeFormat'
export default {
export default defineComponent({
name: 'toot',
props: {
displayNameStyle: {
@ -61,46 +62,53 @@ export default {
default: TimeFormat.Absolute.value
}
},
computed: {
sampleIcon() {
return 'https://github.com/h3poteto/whalebird-desktop/raw/master/build/icons/256x256.png'
},
username() {
switch (this.displayNameStyle) {
setup(props) {
const { displayNameStyle, timeFormat } = toRefs(props)
const sampleIcon = 'https://github.com/h3poteto/whalebird-desktop/raw/master/build/icons/256x256.png'
const status = '<p>Sample status</p>'
const reblogsCount = 1
const favouritesCount = 5
const username = computed(() => {
switch (displayNameStyle.value) {
case DisplayStyle.DisplayNameAndUsername.value:
case DisplayStyle.DisplayName.value:
return 'Whalebird'
default:
return 'whalebird@mastodon.social'
}
},
accountName() {
switch (this.displayNameStyle) {
})
const accountName = computed(() => {
switch (displayNameStyle.value) {
case DisplayStyle.DisplayNameAndUsername.value:
return 'whalebird@mastodon.social'
default:
return ''
}
},
timestamp() {
switch (this.timeFormat) {
})
const timestamp = computed(() => {
switch (timeFormat.value) {
case TimeFormat.Absolute.value:
return '2018-08-12 20:35:41'
case TimeFormat.Relative.value:
return moment('2018-08-12 20:35:41').fromNow()
default:
return '2018-08-12 20:35:41'
}
},
status() {
return '<p>Sample status</p>'
},
reblogsCount() {
return 1
},
favouritesCount() {
return 5
})
return {
sampleIcon,
username,
accountName,
timestamp,
status,
reblogsCount,
favouritesCount
}
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -40,104 +40,103 @@
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex'
<script lang="ts">
import { defineComponent, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useI18next } from 'vue3-i18next'
import { useStore } from '@/store'
import { ACTION_TYPES } from '@/store/Preferences/General'
export default {
export default defineComponent({
name: 'general',
computed: {
...mapState('Preferences/General', {
loading: state => state.loading
}),
...mapState({
backgroundColor: state => state.App.theme.background_color
}),
...mapGetters('Preferences/General', ['notDarwin']),
sound_fav_rb: {
get() {
return this.$store.state.Preferences.General.general.sound.fav_rb
},
set(value) {
this.$store.dispatch('Preferences/General/updateSound', {
setup() {
const space = 'Preferences/General'
const store = useStore()
const i18n = useI18next()
const loading = computed(() => store.state.Preferences.General.loading)
const backgroundColor = computed(() => store.state.App.theme.background_color)
const notDarwin = computed(() => store.getters[`${space}/notDarwin`])
const sound_fav_rb = computed({
get: () => store.state.Preferences.General.general.sound.fav_rb,
set: (value: boolean) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_SOUND}`, {
fav_rb: value
})
}
},
sound_toot: {
get() {
return this.$store.state.Preferences.General.general.sound.toot
},
set(value) {
this.$store.dispatch('Preferences/General/updateSound', {
})
const sound_toot = computed({
get: () => store.state.Preferences.General.general.sound.toot,
set: (value: boolean) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_SOUND}`, {
toot: value
})
}
},
timeline_cw: {
get() {
return this.$store.state.Preferences.General.general.timeline.cw
},
set(value) {
this.$store.dispatch('Preferences/General/updateTimeline', {
})
const timeline_cw = computed({
get: () => store.state.Preferences.General.general.timeline.cw,
set: (value: boolean) =>
store.dispatch('Preferences/General/updateTimeline', {
cw: value
})
}
},
timeline_nsfw: {
get() {
return this.$store.state.Preferences.General.general.timeline.nsfw
},
set(value) {
this.$store.dispatch('Preferences/General/updateTimeline', {
})
const timeline_nsfw = computed({
get: () => store.state.Preferences.General.general.timeline.nsfw,
set: (value: boolean) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_TIMELINE}`, {
nsfw: value
})
}
},
timeline_hide_attachments: {
get() {
return this.$store.state.Preferences.General.general.timeline.hideAllAttachments
},
set(value) {
this.$store.dispatch('Preferences/General/updateTimeline', {
})
const timeline_hide_attachments = computed({
get: () => store.state.Preferences.General.general.timeline.hideAllAttachments,
set: (value: boolean) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_TIMELINE}`, {
hideAllAttachments: value
})
}
},
other_launch: {
get() {
return this.$store.state.Preferences.General.general.other.launch
},
set(value) {
this.$store.dispatch('Preferences/General/updateOther', {
})
const other_launch = computed({
get: () => store.state.Preferences.General.general.other.launch,
set: (value: boolean) =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_OTHER}`, {
launch: value
})
}
}
},
created() {
this.$store.dispatch('Preferences/General/loadGeneral').catch(() => {
this.$message({
message: this.$t('message.preferences_load_error'),
type: 'error'
})
onMounted(() => {
store.dispatch(`${space}/${ACTION_TYPES.LOAD_GENERAL}`).catch(() => {
ElMessage({
message: i18n.t('message.preferences_load_error'),
type: 'error'
})
})
})
},
methods: {
reset() {
this.$store
.dispatch('Preferences/General/reset')
const reset = () => {
store
.dispatch(`${space}/${ACTION_TYPES.RESET}`)
.then(language => {
this.$i18n.locale = language
i18n.changeLanguage(language)
})
.catch(() => {
this.$message({
message: this.$t('message.preferences_load_error'),
ElMessage({
message: i18n.t('message.preferences_load_error'),
type: 'error'
})
})
}
return {
loading,
backgroundColor,
notDarwin,
sound_fav_rb,
sound_toot,
timeline_cw,
timeline_nsfw,
timeline_hide_attachments,
other_launch,
reset
}
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -30,73 +30,79 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent, computed, onMounted } from 'vue'
import { useI18next } from 'vue3-i18next'
import { ElMessage } from 'element-plus'
import { useStore } from '@/store'
import Language from '~/src/constants/language'
import { ACTION_TYPES } from '@/store/Preferences/Language'
export default {
export default defineComponent({
name: 'language',
data() {
return {
languages: [
Language.cs,
Language.de,
Language.en,
Language.es_es,
Language.fr,
Language.gd,
Language.id,
Language.it,
Language.ja,
Language.ko,
Language.no,
Language.pl,
Language.pt_pt,
Language.ru,
Language.si,
Language.sv_se,
Language.tzm,
Language.zh_cn,
Language.zh_tw
]
}
},
computed: {
displayLanguage: {
get() {
return this.$store.state.Preferences.Language.language.language
},
set(value) {
this.$store.dispatch('Preferences/Language/changeLanguage', value).then(key => {
this.$i18n.locale = key
setup() {
const space = 'Preferences/Language'
const store = useStore()
const i18n = useI18next()
const languages = [
Language.cs,
Language.de,
Language.en,
Language.es_es,
Language.fr,
Language.gd,
Language.id,
Language.it,
Language.ja,
Language.ko,
Language.no,
Language.pl,
Language.pt_pt,
Language.ru,
Language.si,
Language.sv_se,
Language.tzm,
Language.zh_cn,
Language.zh_tw
]
const displayLanguage = computed({
get: () => store.state.Preferences.Language.language.language,
set: (value: string) =>
store.dispatch(`${space}/${ACTION_TYPES.CHANGE_LANGUAGE}`, value).then(key => {
i18n.changeLanguage(key)
})
}
},
spellcheck: {
get() {
return this.$store.state.Preferences.Language.language.spellchecker.enabled
},
set(value) {
this.$store.dispatch('Preferences/Language/toggleSpellchecker', value)
}
},
spellcheckLanguages: {
get() {
return this.$store.state.Preferences.Language.language.spellchecker.languages
},
set(value) {
this.$store.dispatch('Preferences/Language/updateSpellcheckerLanguages', value).catch(() => {
this.$message({
message: this.$t('message.language_not_support_spellchecker_error'),
})
const spellcheck = computed({
get: () => store.state.Preferences.Language.language.spellchecker.enabled,
set: (value: boolean) => store.dispatch(`${space}/${ACTION_TYPES.TOGGLE_SPELLCHECKER}`, value)
})
const spellcheckLanguages = computed({
get: () => store.state.Preferences.Language.language.spellchecker.languages,
set: (value: Array<string>) =>
store.dispatch('Preferences/Language/updateSpellcheckerLanguages', value).catch(() => {
ElMessage({
message: i18n.t('message.language_not_support_spellchecker_error'),
type: 'error'
})
})
}
})
onMounted(() => {
store.dispatch(`${space}/${ACTION_TYPES.LOAD_LANGUAGE}`)
})
return {
languages,
displayLanguage,
spellcheck,
spellcheckLanguages
}
},
created() {
this.$store.dispatch('Preferences/Language/loadLanguage')
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -40,76 +40,70 @@
</div>
</template>
<script>
import { mapGetters } from 'vuex'
<script lang="ts">
import { defineComponent, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useI18next } from 'vue3-i18next'
import { useStore } from '@/store'
import { ACTION_TYPES } from '@/store/Preferences/Network'
export default {
export default defineComponent({
name: 'network',
computed: {
...mapGetters('Preferences/Network', ['manualProxyConfiguration']),
source: {
get() {
return this.$store.state.Preferences.Network.source
},
set(value) {
this.$store.dispatch('Preferences/Network/changeSource', value)
}
},
proxyProtocol: {
get() {
return this.$store.state.Preferences.Network.proxy.protocol
},
set(value) {
this.$store.dispatch('Preferences/Network/updateProtocol', value)
}
},
proxyHost: {
get() {
return this.$store.state.Preferences.Network.proxy.host
},
set(value) {
this.$store.dispatch('Preferences/Network/updateHost', value)
}
},
proxyPort: {
get() {
return this.$store.state.Preferences.Network.proxy.port
},
set(value) {
this.$store.dispatch('Preferences/Network/updatePort', value)
}
},
proxyUsername: {
get() {
return this.$store.state.Preferences.Network.proxy.username
},
set(value) {
this.$store.dispatch('Preferences/Network/updateUsername', value)
}
},
proxyPassword: {
get() {
return this.$store.state.Preferences.Network.proxy.password
},
set(value) {
this.$store.dispatch('Preferences/Network/updatePassword', value)
}
}
},
created() {
this.$store.dispatch('Preferences/Network/loadProxy').catch(() => {
this.$message({
message: this.$t('message.preferences_load_error'),
type: 'error'
setup() {
const space = 'Preferences/Network'
const store = useStore()
const i18n = useI18next()
const manualProxyConfiguration = computed(() => store.getters[`${space}/manualProxyConfiguration`])
const source = computed({
get: () => store.state.Preferences.Network.source,
set: value => store.dispatch(`${space}/${ACTION_TYPES.CHANGE_SOURCE}`, value)
})
const proxyProtocol = computed({
get: () => store.state.Preferences.Network.proxy.protocol,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_PROTOCOL}`, value)
})
const proxyHost = computed({
get: () => store.state.Preferences.Network.proxy.host,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_HOST}`, value)
})
const proxyPort = computed({
get: () => store.state.Preferences.Network.proxy.port,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_PORT}`, value)
})
const proxyUsername = computed({
get: () => store.state.Preferences.Network.proxy.username,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_USERNAME}`, value)
})
const proxyPassword = computed({
get: () => store.state.Preferences.Network.proxy.password,
set: value => store.dispatch(`${space}/${ACTION_TYPES.UPDATE_PASSWORD}`, value)
})
onMounted(() => {
store.dispatch(`${space}/${ACTION_TYPES.LOAD_PROXY}`).catch(() => {
ElMessage({
message: i18n.t('message.preferences_load_error'),
type: 'error'
})
})
})
},
methods: {
onSave() {
this.$store.dispatch('Preferences/Network/saveProxyConfig')
const onSave = () => store.dispatch(`${space}/${ACTION_TYPES.SAVE_PROXY_CONFIG}`)
return {
manualProxyConfiguration,
source,
proxyProtocol,
proxyHost,
proxyPort,
proxyUsername,
proxyPassword,
onSave
}
}
}
},
methods: {}
})
</script>
<style lang="scss" scoped>

View File

@ -36,110 +36,107 @@
</div>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useI18next } from 'vue3-i18next'
import { useStore } from '@/store'
import { ACTION_TYPES } from '@/store/Preferences/Notification'
export default defineComponent({
name: 'notification',
computed: {
notifyReply: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.reply
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
setup() {
const space = 'Preferences/Notification'
const store = useStore()
const i18n = useI18next()
const notifyReply = computed({
get: () => store.state.Preferences.Notification.notification.notify.reply,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
reply: value
})
}
},
notifyReblog: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.reblog
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyReblog = computed({
get: () => store.state.Preferences.Notification.notification.notify.reblog,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
reblog: value
})
}
},
notifyFavourite: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.favourite
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyFavourite = computed({
get: () => store.state.Preferences.Notification.notification.notify.favourite,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
favourite: value
})
}
},
notifyFollow: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.follow
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyFollow = computed({
get: () => store.state.Preferences.Notification.notification.notify.follow,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
follow: value
})
}
},
notifyFollowRequest: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.follow_request
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyFollowRequest = computed({
get: () => store.state.Preferences.Notification.notification.notify.follow_request,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
follow_request: value
})
}
},
notifyReaction: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.reaction
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyReaction = computed({
get: () => store.state.Preferences.Notification.notification.notify.reaction,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
reaction: value
})
}
},
notifyStatus: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.status
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyStatus = computed({
get: () => store.state.Preferences.Notification.notification.notify.status,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
status: value
})
}
},
notifyPollVote: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.poll_vote
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyPollVote = computed({
get: () => store.state.Preferences.Notification.notification.notify.poll_vote,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
poll_vote: value
})
}
},
notifyPollExpired: {
get() {
return this.$store.state.Preferences.Notification.notification.notify.poll_expired
},
set(value) {
this.$store.dispatch('Preferences/Notification/updateNotify', {
})
const notifyPollExpired = computed({
get: () => store.state.Preferences.Notification.notification.notify.poll_expired,
set: value =>
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_NOTIFY}`, {
poll_expired: value
})
}
}
},
created() {
this.$store.dispatch('Preferences/Notification/loadNotification').catch(() => {
this.$message({
message: this.$t('message.preferences_load_error'),
type: 'error'
})
onMounted(() => {
store.dispatch(`${space}/${ACTION_TYPES.LOAD_NOTIFICATION}`).catch(() => {
ElMessage({
message: i18n.t('message.preferences_load_error'),
type: 'error'
})
})
})
}
}
return {
notifyReply,
notifyReblog,
notifyFavourite,
notifyFollow,
notifyFollowRequest,
notifyReaction,
notifyStatus,
notifyPollVote,
notifyPollExpired
}
},
created() {}
})
</script>
<style lang="scss" scoped>

View File

@ -30,22 +30,30 @@ const mutations: MutationTree<AccountState> = {
}
}
export const ACTION_TYPES = {
LOAD_ACCOUNTS: 'loadAccounts',
REMOVE_ACCOUNT: 'removeAccount',
FORWARD_ACCOUNT: 'forwardAccount',
BACKWARD_ACCOUNT: 'backwardAccount',
REMOVE_ALL_ACCOUNTS: 'removeAllAccounts'
}
const actions: ActionTree<AccountState, RootState> = {
loadAccounts: async ({ commit }): Promise<Array<LocalAccount>> => {
[ACTION_TYPES.LOAD_ACCOUNTS]: async ({ commit }): Promise<Array<LocalAccount>> => {
const accounts = await win.ipcRenderer.invoke('list-accounts')
commit(MUTATION_TYPES.UPDATE_ACCOUNTS, accounts)
return accounts
},
removeAccount: async (_, account: LocalAccount) => {
[ACTION_TYPES.REMOVE_ACCOUNT]: async (_, account: LocalAccount) => {
await win.ipcRenderer.invoke('remove-account', account._id)
},
forwardAccount: async (_, account: LocalAccount) => {
[ACTION_TYPES.FORWARD_ACCOUNT]: async (_, account: LocalAccount) => {
await win.ipcRenderer.invoke('forward-account', toRaw(account))
},
backwardAccount: async (_, account: LocalAccount) => {
[ACTION_TYPES.BACKWARD_ACCOUNT]: async (_, account: LocalAccount) => {
await win.ipcRenderer.invoke('backward-account', toRaw(account))
},
removeAllAccounts: async () => {
[ACTION_TYPES.REMOVE_ALL_ACCOUNTS]: async () => {
await win.ipcRenderer.invoke('remove-all-accounts')
}
}

View File

@ -4,12 +4,13 @@ import TimeFormat from '~/src/constants/timeFormat'
import { LightTheme, ThemeColorType } from '~/src/constants/themeColor'
import DefaultFonts from '@/utils/fonts'
import { Module, MutationTree, ActionTree } from 'vuex'
import { toRaw } from 'vue'
import { RootState } from '@/store'
import { Appearance } from '~/src/types/appearance'
import { BaseConfig } from '~/src/types/preference'
import { MyWindow } from '~/src/types/global'
const win = (window as any) as MyWindow
const win = window as any as MyWindow
export type AppearanceState = {
appearance: Appearance
@ -43,19 +44,31 @@ const mutations: MutationTree<AppearanceState> = {
}
}
export const ACTION_TYPES = {
LOAD_APPEARANCE: 'loadAppearance',
LOAD_FONTS: 'loadFonts',
UPDATE_THEME: 'updateTheme',
UPDATE_FONT_SIZE: 'updateFontSize',
UPDATE_DISPLAY_NAME_STYLE: 'updateDisplayNameStyle',
UPDATE_TIME_FORMAT: 'updateTimeFormat',
UPDATE_CUSTOM_THEME_COLOR: 'updateCustomThemeColor',
UPDATE_FONT: 'updateFont',
UPDATE_TOOT_PADDING: 'updateTootPadding'
}
const actions: ActionTree<AppearanceState, RootState> = {
loadAppearance: async ({ commit }) => {
[ACTION_TYPES.LOAD_APPEARANCE]: async ({ commit }) => {
const conf: BaseConfig = await win.ipcRenderer.invoke('get-preferences')
commit(MUTATION_TYPES.UPDATE_APPEARANCE, conf.appearance)
return conf
},
loadFonts: async ({ commit }) => {
[ACTION_TYPES.LOAD_FONTS]: async ({ commit }) => {
const fonts: Array<string> = await win.ipcRenderer.invoke('list-fonts')
commit(MUTATION_TYPES.UPDATE_FONTS, [DefaultFonts[0]].concat(fonts))
return fonts
},
updateTheme: async ({ dispatch, commit, state }, themeKey: string) => {
const newAppearance: Appearance = Object.assign({}, state.appearance, {
[ACTION_TYPES.UPDATE_THEME]: async ({ dispatch, commit, state }, themeKey: string) => {
const newAppearance: Appearance = Object.assign({}, toRaw(state.appearance), {
theme: themeKey
})
const config = {
@ -65,8 +78,8 @@ const actions: ActionTree<AppearanceState, RootState> = {
commit(MUTATION_TYPES.UPDATE_APPEARANCE, conf.appearance)
dispatch('App/loadPreferences', null, { root: true })
},
updateFontSize: async ({ dispatch, commit, state }, fontSize: number) => {
const newAppearance: Appearance = Object.assign({}, state.appearance, {
[ACTION_TYPES.UPDATE_FONT_SIZE]: async ({ dispatch, commit, state }, fontSize: number) => {
const newAppearance: Appearance = Object.assign({}, toRaw(state.appearance), {
fontSize: fontSize
})
const config = {
@ -76,8 +89,8 @@ const actions: ActionTree<AppearanceState, RootState> = {
commit(MUTATION_TYPES.UPDATE_APPEARANCE, conf.appearance)
dispatch('App/loadPreferences', null, { root: true })
},
updateDisplayNameStyle: async ({ dispatch, commit, state }, value: number) => {
const newAppearance: Appearance = Object.assign({}, state.appearance, {
[ACTION_TYPES.UPDATE_DISPLAY_NAME_STYLE]: async ({ dispatch, commit, state }, value: number) => {
const newAppearance: Appearance = Object.assign({}, toRaw(state.appearance), {
displayNameStyle: value
})
const config = {
@ -87,8 +100,8 @@ const actions: ActionTree<AppearanceState, RootState> = {
dispatch('App/loadPreferences', null, { root: true })
commit(MUTATION_TYPES.UPDATE_APPEARANCE, conf.appearance)
},
updateTimeFormat: async ({ dispatch, commit, state }, value: number) => {
const newAppearance: Appearance = Object.assign({}, state.appearance, {
[ACTION_TYPES.UPDATE_TIME_FORMAT]: async ({ dispatch, commit, state }, value: number) => {
const newAppearance: Appearance = Object.assign({}, toRaw(state.appearance), {
timeFormat: value
})
const config = {
@ -98,8 +111,8 @@ const actions: ActionTree<AppearanceState, RootState> = {
dispatch('App/loadPreferences', null, { root: true })
commit(MUTATION_TYPES.UPDATE_APPEARANCE, conf.appearance)
},
updateCustomThemeColor: async ({ dispatch, state, commit }, value: object) => {
const newCustom: ThemeColorType = Object.assign({}, state.appearance.customThemeColor, value)
[ACTION_TYPES.UPDATE_CUSTOM_THEME_COLOR]: async ({ dispatch, state, commit }, value: object) => {
const newCustom: ThemeColorType = Object.assign({}, toRaw(state.appearance.customThemeColor), value)
const newAppearance: Appearance = Object.assign({}, state.appearance, {
customThemeColor: newCustom
})
@ -110,8 +123,8 @@ const actions: ActionTree<AppearanceState, RootState> = {
commit(MUTATION_TYPES.UPDATE_APPEARANCE, conf.appearance)
dispatch('App/loadPreferences', null, { root: true })
},
updateFont: async ({ dispatch, state, commit }, value: string) => {
const newAppearance: Appearance = Object.assign({}, state.appearance, {
[ACTION_TYPES.UPDATE_FONT]: async ({ dispatch, state, commit }, value: string) => {
const newAppearance: Appearance = Object.assign({}, toRaw(state.appearance), {
font: value
})
const config = {
@ -121,8 +134,8 @@ const actions: ActionTree<AppearanceState, RootState> = {
commit(MUTATION_TYPES.UPDATE_APPEARANCE, conf.appearance)
dispatch('App/loadPreferences', null, { root: true })
},
updateTootPadding: async ({ dispatch, state, commit }, value: number) => {
const newAppearance: Appearance = Object.assign({}, state.appearance, {
[ACTION_TYPES.UPDATE_TOOT_PADDING]: async ({ dispatch, state, commit }, value: number) => {
const newAppearance: Appearance = Object.assign({}, toRaw(state.appearance), {
tootPadding: value
})
const config = {

View File

@ -45,15 +45,23 @@ const mutations: MutationTree<GeneralState> = {
}
}
export const ACTION_TYPES = {
LOAD_GENERAL: 'loadGeneral',
UPDATE_SOUND: 'updateSound',
UPDATE_TIMELINE: 'updateTimeline',
UPDATE_OTHER: 'updateOther',
RESET: 'reset'
}
const actions: ActionTree<GeneralState, RootState> = {
loadGeneral: async ({ commit }) => {
[ACTION_TYPES.LOAD_GENERAL]: async ({ commit }) => {
const conf: BaseConfig = await win.ipcRenderer.invoke('get-preferences').finally(() => {
commit(MUTATION_TYPES.CHANGE_LOADING, false)
})
commit(MUTATION_TYPES.UPDATE_GENERAL, conf.general as General)
return conf
},
updateSound: async ({ commit, state }, sound: object) => {
[ACTION_TYPES.UPDATE_SOUND]: async ({ commit, state }, sound: object) => {
commit(MUTATION_TYPES.CHANGE_LOADING, true)
const newSound: Sound = Object.assign({}, state.general.sound, sound)
const newGeneral: General = Object.assign({}, toRaw(state.general), {
@ -67,7 +75,7 @@ const actions: ActionTree<GeneralState, RootState> = {
})
commit(MUTATION_TYPES.UPDATE_GENERAL, conf.general as General)
},
updateTimeline: async ({ commit, state, dispatch }, timeline: object) => {
[ACTION_TYPES.UPDATE_TIMELINE]: async ({ commit, state, dispatch }, timeline: object) => {
commit(MUTATION_TYPES.CHANGE_LOADING, true)
const newTimeline: Timeline = Object.assign({}, state.general.timeline, timeline)
const newGeneral: General = Object.assign({}, toRaw(state.general), {
@ -82,7 +90,7 @@ const actions: ActionTree<GeneralState, RootState> = {
commit(MUTATION_TYPES.UPDATE_GENERAL, conf.general as General)
dispatch('App/loadPreferences', null, { root: true })
},
updateOther: async ({ commit, state, dispatch }, other: {}) => {
[ACTION_TYPES.UPDATE_OTHER]: async ({ commit, state, dispatch }, other: {}) => {
commit(MUTATION_TYPES.CHANGE_LOADING, true)
const newOther: Other = Object.assign({}, state.general.other, other)
const newGeneral: General = Object.assign({}, toRaw(state.general), {
@ -98,7 +106,7 @@ const actions: ActionTree<GeneralState, RootState> = {
dispatch('App/loadPreferences', null, { root: true })
await win.ipcRenderer.invoke('change-auto-launch', newOther.launch)
},
reset: async ({ commit, dispatch }): Promise<string> => {
[ACTION_TYPES.RESET]: async ({ commit, dispatch }): Promise<string> => {
commit(MUTATION_TYPES.CHANGE_LOADING, true)
try {
const conf: BaseConfig = await win.ipcRenderer.invoke('reset-preferences')

View File

@ -5,7 +5,7 @@ import { Language as LanguageSet } from '~/src/types/language'
import { BaseConfig } from '~/src/types/preference'
import { MyWindow } from '~/src/types/global'
const win = (window as any) as MyWindow
const win = window as any as MyWindow
export type LanguageState = {
language: LanguageSet
@ -43,23 +43,30 @@ const mutations: MutationTree<LanguageState> = {
}
}
export const ACTION_TYPES = {
LOAD_LANGUAGE: 'loadLanguage',
CHANGE_LANGUAGE: 'changeLanguage',
TOGGLE_SPELLCHECKER: 'toggleSpellchecker',
UPDATE_SPELLCHECKER_LANGUAGES: 'updateSpellcheckerLanguages'
}
const actions: ActionTree<LanguageState, RootState> = {
loadLanguage: async ({ commit }): Promise<string> => {
[ACTION_TYPES.LOAD_LANGUAGE]: async ({ commit }): Promise<string> => {
const conf: BaseConfig = await win.ipcRenderer.invoke('get-preferences')
commit(MUTATION_TYPES.UPDATE_LANGUAGE, conf.language as LanguageSet)
return conf.language.language
},
changeLanguage: async ({ commit }, key: string): Promise<string> => {
[ACTION_TYPES.CHANGE_LANGUAGE]: async ({ commit }, key: string): Promise<string> => {
const value: string = await win.ipcRenderer.invoke('change-language', key)
commit(MUTATION_TYPES.CHANGE_LANGUAGE, value)
return value
},
toggleSpellchecker: async ({ commit }, enabled: boolean) => {
[ACTION_TYPES.TOGGLE_SPELLCHECKER]: async ({ commit }, enabled: boolean) => {
const value: boolean = await win.ipcRenderer.invoke('toggle-spellchecker', enabled)
commit(MUTATION_TYPES.TOGGLE_SPELLCHECKER, value)
return value
},
updateSpellcheckerLanguages: async ({ commit }, languages: Array<string>) => {
[ACTION_TYPES.UPDATE_SPELLCHECKER_LANGUAGES]: async ({ commit }, languages: Array<string>) => {
const langs: Array<string> = await win.ipcRenderer.invoke('update-spellchecker-languages', languages)
commit(MUTATION_TYPES.UPDATE_SPELLCHECKER_LANGUAGES, langs)
return langs

View File

@ -4,7 +4,7 @@ import { BaseConfig } from '~/src/types/preference'
import { Proxy, ProxySource, ProxyProtocol, ManualProxy } from '~/src/types/proxy'
import { MyWindow } from '~/src/types/global'
const win = (window as any) as MyWindow
const win = window as any as MyWindow
export type NetworkState = {
source: ProxySource
@ -91,31 +91,42 @@ const mutations: MutationTree<NetworkState> = {
}
}
export const ACTION_TYPES = {
LOAD_PROXY: 'loadProxy',
CHANGE_SOURCE: 'changeSource',
UPDATE_PROTOCOL: 'updateProtocol',
UPDATE_HOST: 'updateHost',
UPDATE_PORT: 'updatePort',
UPDATE_USERNAME: 'updateUsername',
UPDATE_PASSWORD: 'updatePassword',
SAVE_PROXY_CONFIG: 'saveProxyConfig'
}
const actions: ActionTree<NetworkState, RootState> = {
loadProxy: async ({ commit }) => {
[ACTION_TYPES.LOAD_PROXY]: async ({ commit }) => {
const conf: BaseConfig = await win.ipcRenderer.invoke('get-preferences')
commit(MUTATION_TYPES.UPDATE_PROXY, conf.proxy as Proxy)
return conf
},
changeSource: ({ commit }, source: string) => {
[ACTION_TYPES.CHANGE_SOURCE]: ({ commit }, source: string) => {
commit(MUTATION_TYPES.CHANGE_SOURCE, source)
},
updateProtocol: ({ commit }, protocol: string) => {
[ACTION_TYPES.UPDATE_PROTOCOL]: ({ commit }, protocol: string) => {
commit(MUTATION_TYPES.UPDATE_PROTOCOL, protocol)
},
updateHost: ({ commit }, host: string) => {
[ACTION_TYPES.UPDATE_HOST]: ({ commit }, host: string) => {
commit(MUTATION_TYPES.UPDATE_HOST, host)
},
updatePort: ({ commit }, port: string) => {
[ACTION_TYPES.UPDATE_PORT]: ({ commit }, port: string) => {
commit(MUTATION_TYPES.UPDATE_PORT, port)
},
updateUsername: ({ commit }, username: string) => {
[ACTION_TYPES.UPDATE_USERNAME]: ({ commit }, username: string) => {
commit(MUTATION_TYPES.UPDATE_USERNAME, username)
},
updatePassword: ({ commit }, password: string) => {
[ACTION_TYPES.UPDATE_PASSWORD]: ({ commit }, password: string) => {
commit(MUTATION_TYPES.UPDATE_PASSWORD, password)
},
saveProxyConfig: async ({ state }) => {
[ACTION_TYPES.SAVE_PROXY_CONFIG]: async ({ state }) => {
const proxy: Proxy = {
source: state.source,
manualProxyConfig: state.proxy

View File

@ -4,7 +4,7 @@ import { Notify } from '~/src/types/notify'
import { BaseConfig, Notification } from '~/src/types/preference'
import { MyWindow } from '~/src/types/global'
const win = (window as any) as MyWindow
const win = window as any as MyWindow
export type NotificationState = {
notification: Notification
@ -36,13 +36,18 @@ const mutations: MutationTree<NotificationState> = {
}
}
export const ACTION_TYPES = {
LOAD_NOTIFICATION: 'loadNotification',
UPDATE_NOTIFY: 'updateNotify'
}
const actions: ActionTree<NotificationState, RootState> = {
loadNotification: async ({ commit }) => {
[ACTION_TYPES.LOAD_NOTIFICATION]: async ({ commit }) => {
const conf: BaseConfig = await win.ipcRenderer.invoke('get-preferences')
commit(MUTATION_TYPES.UPDATE_NOTIFICATION, conf.notification)
return conf
},
updateNotify: async ({ commit, state, dispatch }, notify: object) => {
[ACTION_TYPES.UPDATE_NOTIFY]: async ({ commit, state, dispatch }, notify: object) => {
const newNotify: Notify = Object.assign({}, state.notification.notify, notify)
const newNotification: Notification = Object.assign({}, state.notification, {
notify: newNotify