diff --git a/package.json b/package.json
index 20c01a0b3..1d0382d46 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"ci-eslint": "yarn exec eslint",
"ci-stylelint": "yarn exec stylelint '**/*.scss' '**/*.vue'",
"lint": "yarn ci-biome; yarn ci-eslint; yarn ci-stylelint",
- "lint-fix": "yarn exec eslint --fix; yarn exec stylelint '**/*.scss' '**/*.vue' --fix; biome check --write"
+ "lint-fix": "yarn exec eslint -- --fix; yarn exec stylelint '**/*.scss' '**/*.vue' --fix; biome check --write"
},
"dependencies": {
"@babel/runtime": "7.28.4",
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index b7e97cf45..97f9b8a42 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -17,7 +17,7 @@ config.autoAddCss = false
import App from '../App.vue'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import FaviconService from '../services/favicon_service/favicon_service.js'
-import { applyConfig } from '../services/style_setter/style_setter.js'
+import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
import {
windowHeight,
@@ -88,25 +88,25 @@ const getInstanceConfig = async ({ store }) => {
data.pleroma,
)
useInstanceStore().set({
- name: 'textlimit',
+ path: 'textlimit',
value: textlimit,
})
useInstanceStore().set({
- name: 'accountApprovalRequired',
+ path: 'accountApprovalRequired',
value: data.approval_required,
})
useInstanceStore().set({
- name: 'birthdayRequired',
+ path: 'birthdayRequired',
value: !!data.pleroma?.metadata.birthday_required,
})
useInstanceStore().set({
- name: 'birthdayMinAge',
+ path: 'birthdayMinAge',
value: data.pleroma?.metadata.birthday_min_age || 0,
})
if (vapidPublicKey) {
useInstanceStore().set({
- name: 'vapidPublicKey',
+ path: 'vapidPublicKey',
value: vapidPublicKey,
})
}
@@ -258,7 +258,7 @@ const getAppSecret = async ({ store }) => {
const resolveStaffAccounts = ({ store, accounts }) => {
const nicknames = accounts.map((uri) => uri.split('/').pop())
useInstanceStore().set({
- name: 'staffAccounts',
+ path: 'staffAccounts',
value: nicknames,
})
}
@@ -384,20 +384,20 @@ const getNodeInfo = async ({ store }) => {
const software = data.software
useInstanceStore().set({
- name: 'backendVersion',
+ path: 'backendVersion',
value: software.version,
})
useInstanceStore().set({
- name: 'backendRepository',
+ path: 'backendRepository',
value: software.repository,
})
const priv = metadata.private
- useInstanceStore().set({ name: 'privateMode', value: priv })
+ useInstanceStore().set({ path: 'privateMode', value: priv })
const frontendVersion = window.___pleromafe_commit_hash
useInstanceStore().set({
- name: 'frontendVersion',
+ path: 'frontendVersion',
value: frontendVersion,
})
@@ -547,7 +547,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
return Promise.reject(e)
}
- applyConfig(store.state.config, i18n.global)
+ applyStyleConfig(store.state.config, i18n.global)
// Now we can try getting the server settings and logging in
// Most of these are preloaded into the index.html so blocking is minimized
diff --git a/src/components/timeago/timeago.js b/src/components/timeago/timeago.js
new file mode 100644
index 000000000..efb92d4cd
--- /dev/null
+++ b/src/components/timeago/timeago.js
@@ -0,0 +1,127 @@
+import * as DateUtils from 'src/services/date_utils/date_utils.js'
+import localeService from 'src/services/locale/locale.service.js'
+
+export default {
+ name: 'Timeago',
+ props: ['time', 'autoUpdate', 'longFormat', 'nowThreshold', 'templateKey'],
+ data() {
+ return {
+ relativeTimeMs: 0,
+ relativeTime: { key: 'time.now', num: 0 },
+ interval: null,
+ }
+ },
+ computed: {
+ shouldUseAbsoluteTimeFormat() {
+ if (!this.$store.getters.mergedConfig.useAbsoluteTimeFormat) {
+ return false
+ }
+ return (
+ DateUtils.durationStrToMs(
+ this.$store.getters.mergedConfig.absoluteTimeFormatMinAge,
+ ) <= this.relativeTimeMs
+ )
+ },
+ time12hFormat() {
+ return this.$store.getters.mergedConfig.absoluteTimeFormat12h === '12h'
+ },
+ browserLocale() {
+ return localeService.internalToBrowserLocale(this.$i18n.locale)
+ },
+ timeAsDate() {
+ return typeof this.time === 'string'
+ ? new Date(Date.parse(this.time))
+ : this.time
+ },
+ localeDateString() {
+ return this.timeAsDate.toLocaleString(this.browserLocale)
+ },
+ relativeTimeString() {
+ const timeString = this.$i18n.t(
+ this.relativeTime.key,
+ [this.relativeTime.num],
+ this.relativeTime.num,
+ )
+
+ if (
+ typeof this.templateKey === 'string' &&
+ this.relativeTime.key !== 'time.now'
+ ) {
+ return this.$i18n.t(this.templateKey, [timeString])
+ }
+
+ return timeString
+ },
+ absoluteTimeString() {
+ if (this.longFormat) {
+ return this.localeDateString
+ }
+ const now = new Date()
+ const formatter = (() => {
+ if (DateUtils.isSameDay(this.timeAsDate, now)) {
+ return new Intl.DateTimeFormat(this.browserLocale, {
+ minute: 'numeric',
+ hour: 'numeric',
+ hour12: this.time12hFormat,
+ })
+ } else if (DateUtils.isSameMonth(this.timeAsDate, now)) {
+ return new Intl.DateTimeFormat(this.browserLocale, {
+ month: 'short',
+ day: 'numeric',
+ hour12: this.time12hFormat,
+ })
+ } else if (DateUtils.isSameYear(this.timeAsDate, now)) {
+ return new Intl.DateTimeFormat(this.browserLocale, {
+ month: 'short',
+ day: 'numeric',
+ hour12: this.time12hFormat,
+ })
+ } else {
+ return new Intl.DateTimeFormat(this.browserLocale, {
+ year: 'numeric',
+ month: 'short',
+ hour12: this.time12hFormat,
+ })
+ }
+ })()
+
+ return formatter.format(this.timeAsDate)
+ },
+ relativeOrAbsoluteTimeString() {
+ return this.shouldUseAbsoluteTimeFormat
+ ? this.absoluteTimeString
+ : this.relativeTimeString
+ },
+ },
+ watch: {
+ time(newVal, oldVal) {
+ if (oldVal !== newVal) {
+ clearTimeout(this.interval)
+ this.refreshRelativeTimeObject()
+ }
+ },
+ },
+ created() {
+ this.refreshRelativeTimeObject()
+ },
+ unmounted() {
+ clearTimeout(this.interval)
+ },
+ methods: {
+ refreshRelativeTimeObject() {
+ const nowThreshold =
+ typeof this.nowThreshold === 'number' ? this.nowThreshold : 1
+ this.relativeTimeMs = DateUtils.relativeTimeMs(this.time)
+ this.relativeTime = this.longFormat
+ ? DateUtils.relativeTime(this.time, nowThreshold)
+ : DateUtils.relativeTimeShort(this.time, nowThreshold)
+
+ if (this.autoUpdate) {
+ this.interval = setTimeout(
+ this.refreshRelativeTimeObject,
+ 1000 * this.autoUpdate,
+ )
+ }
+ },
+ },
+}
diff --git a/src/components/timeago/timeago.vue b/src/components/timeago/timeago.vue
index 60cf347bf..eeb00db8b 100644
--- a/src/components/timeago/timeago.vue
+++ b/src/components/timeago/timeago.vue
@@ -7,132 +7,4 @@
-
+
diff --git a/src/modules/config.js b/src/modules/config.js
index 82acf8162..b68d547df 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -3,7 +3,7 @@ import { set } from 'lodash'
import messages from '../i18n/messages'
import localeService from '../services/locale/locale.service.js'
-import { applyConfig } from '../services/style_setter/style_setter.js'
+import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { defaultState, instanceDefaultConfig } from './default_config_state.js'
import { useEmojiStore } from 'src/stores/emoji.js'
@@ -71,7 +71,7 @@ const config = {
mutations: {
setOptionTemporarily(state, { name, value }) {
set(state, name, value)
- applyConfig(state)
+ applyStyleConfig(state)
},
setOption(state, { name, value }) {
set(state, name, value)
@@ -162,7 +162,7 @@ const config = {
} else {
commit('setOption', { name, value })
if (APPEARANCE_SETTINGS_KEYS.has(name)) {
- applyConfig(state)
+ applyStyleConfig(state)
}
if (name.startsWith('theme3hacks')) {
dispatch('applyTheme', { recompile: true })
diff --git a/src/modules/default_config_state.js b/src/modules/default_config_state.js
index 3e39fb1fc..2f18fe9a5 100644
--- a/src/modules/default_config_state.js
+++ b/src/modules/default_config_state.js
@@ -1,9 +1,10 @@
-const browserLocale = (window.navigator.language || 'en').split('-')[0]
+const browserLocale = (navigator.language || 'en').split('-')[0]
/// Instance config entries provided by static config or pleroma api
/// Put settings here only if it does not make sense for a normal user
/// to override it.
export const staticOrApiConfigDefault = {
+ name: 'PleromaFE',
theme: 'pleroma-dark',
palette: null,
style: null,
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 90886b4c5..48f8b9e8a 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -318,9 +318,7 @@ const updateProfileJSON = ({ credentials, params }) => {
credentials,
payload: params,
method: 'PATCH',
- })
- .then((data) => data.json())
- .then((data) => parseUser(data))
+ }).then((data) => parseUser(data))
}
// Params needed:
diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js
index 08034d485..495070b0d 100644
--- a/src/services/style_setter/style_setter.js
+++ b/src/services/style_setter/style_setter.js
@@ -255,7 +255,7 @@ const extractStyleConfig = ({
const defaultStyleConfig = extractStyleConfig(defaultState)
-export const applyConfig = (input) => {
+export const applyStyleConfig = (input) => {
const config = extractStyleConfig(input)
if (config === defaultStyleConfig) {