Make it work with wdw

This commit is contained in:
Essem 2024-01-06 17:03:12 -06:00
parent 8dce31d0ad
commit dcda90373f
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
15 changed files with 109 additions and 136 deletions

View file

@ -67,14 +67,26 @@ const resolveLanguage = (instanceLanguages) => {
const getInstanceConfig = async ({ store }) => { const getInstanceConfig = async ({ store }) => {
try { try {
const res = await preloadFetch('/api/v1/instance') const res = await preloadFetch('/api/v2/instance')
if (res.ok) { if (res.ok) {
const data = await res.json() const data = await res.json()
const textlimit = data.max_toot_chars const textlimit = data.configuration.statuses.max_characters
const vapidPublicKey = data.pleroma.vapid_public_key const vapidPublicKey = data.configuration.vapid.public_key
store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit }) store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit })
store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.approval_required }) const uploadLimits = {
general: data.configuration.media_attachments.video_size_limit,
avatar: "2097152",
background: "2097152",
banner: "2097152"
}
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadLimits.avatar) })
store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadLimits.background) })
store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadLimits.banner) })
store.dispatch('setInstanceOption', { name: 'postFormats', value: data.configuration.statuses.supported_mime_types })
store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.registrations.approval_required })
// don't override cookie if set // don't override cookie if set
if (!Cookies.get('userLanguage')) { if (!Cookies.get('userLanguage')) {
store.dispatch('setOption', { name: 'interfaceLanguage', value: resolveLanguage(data.languages) }) store.dispatch('setOption', { name: 'interfaceLanguage', value: resolveLanguage(data.languages) })
@ -83,6 +95,8 @@ const getInstanceConfig = async ({ store }) => {
if (vapidPublicKey) { if (vapidPublicKey) {
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey }) store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
} }
resolveStaffAccounts({ store, accounts: [data.contact.account.id] })
} else { } else {
throw (res) throw (res)
} }
@ -269,42 +283,33 @@ const getNodeInfo = async ({ store }) => {
if (res.ok) { if (res.ok) {
const data = await res.json() const data = await res.json()
const metadata = data.metadata const metadata = data.metadata
const features = metadata.features
store.dispatch('setInstanceOption', { name: 'name', value: metadata.nodeName }) store.dispatch('setInstanceOption', { name: 'name', value: metadata.nodeName })
store.dispatch('setInstanceOption', { name: 'registrationOpen', value: data.openRegistrations }) store.dispatch('setInstanceOption', { name: 'registrationOpen', value: false }) // registration should be done through the default interface
store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') }) store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: false })
store.dispatch('setInstanceOption', { name: 'safeDM', value: features.includes('safe_dm_mentions') }) store.dispatch('setInstanceOption', { name: 'safeDM', value: false })
store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') }) store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: true })
store.dispatch('setInstanceOption', { name: 'editingAvailable', value: features.includes('editing') }) store.dispatch('setInstanceOption', { name: 'editingAvailable', value: true })
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits }) store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled }) store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
store.dispatch('setInstanceOption', { name: 'translationEnabled', value: features.includes('akkoma:machine_translation') }) store.dispatch('setInstanceOption', { name: 'translationEnabled', value: false }) // idk
const uploadLimits = metadata.uploadLimits store.dispatch('setInstanceOption', { name: 'fieldsLimits', value: 6 }) // todo: expose this on the backend
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadLimits.avatar) })
store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadLimits.background) })
store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadLimits.banner) })
store.dispatch('setInstanceOption', { name: 'fieldsLimits', value: metadata.fieldsLimits })
store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames }) store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: [] })
store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats })
const suggestions = metadata.suggestions store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: true })
store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled }) store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: true })
store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
const software = data.software const software = data.software
store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version }) store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' }) store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' })
const priv = metadata.private store.dispatch('setInstanceOption', { name: 'private', value: false })
store.dispatch('setInstanceOption', { name: 'private', value: priv })
const frontendVersion = window.___pleromafe_commit_hash const frontendVersion = window.___pleromafe_commit_hash
store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion }) store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
const federation = metadata.federation const federation = {}
store.dispatch('setInstanceOption', { store.dispatch('setInstanceOption', {
name: 'tagPolicyAvailable', name: 'tagPolicyAvailable',
@ -314,7 +319,7 @@ const getNodeInfo = async ({ store }) => {
}) })
store.dispatch('setInstanceOption', { name: 'federationPolicy', value: federation }) store.dispatch('setInstanceOption', { name: 'federationPolicy', value: federation })
store.dispatch('setInstanceOption', { name: 'localBubbleInstances', value: metadata.localBubbleInstances }) store.dispatch('setInstanceOption', { name: 'localBubbleInstances', value: [] })
store.dispatch('setInstanceOption', { store.dispatch('setInstanceOption', {
name: 'federating', name: 'federating',
value: typeof federation.enabled === 'undefined' value: typeof federation.enabled === 'undefined'
@ -322,14 +327,11 @@ const getNodeInfo = async ({ store }) => {
: federation.enabled : federation.enabled
}) })
store.dispatch('setInstanceOption', { name: 'publicTimelineVisibility', value: metadata.publicTimelineVisibility }) store.dispatch('setInstanceOption', { name: 'publicTimelineVisibility', value: { bubble: false, local: true, federated: true } })
store.dispatch('setInstanceOption', { name: 'federatedTimelineAvailable', value: metadata.federatedTimelineAvailable }) store.dispatch('setInstanceOption', { name: 'federatedTimelineAvailable', value: true })
const accountActivationRequired = metadata.accountActivationRequired const accountActivationRequired = metadata.accountActivationRequired
store.dispatch('setInstanceOption', { name: 'accountActivationRequired', value: accountActivationRequired }) store.dispatch('setInstanceOption', { name: 'accountActivationRequired', value: true })
const accounts = metadata.staffAccounts
resolveStaffAccounts({ store, accounts })
} else { } else {
throw (res) throw (res)
} }

View file

@ -44,20 +44,6 @@
> >
{{ $t('announcements.mark_as_read_action') }} {{ $t('announcements.mark_as_read_action') }}
</button> </button>
<button
v-if="currentUser && currentUser.role === 'admin'"
class="btn button-default"
@click="enterEditMode"
>
{{ $t('announcements.edit_action') }}
</button>
<button
v-if="currentUser && currentUser.role === 'admin'"
class="btn button-default"
@click="deleteAnnouncement"
>
{{ $t('announcements.delete_action') }}
</button>
</div> </div>
<div <div
v-else v-else

View file

@ -6,46 +6,6 @@
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<section
v-if="currentUser && currentUser.role === 'admin'"
>
<div class="post-form">
<div class="heading">
<h4>{{ $t('announcements.post_form_header') }}</h4>
</div>
<div class="body">
<announcement-editor
:announcement="newAnnouncement"
:disabled="posting"
/>
</div>
<div class="footer">
<button
class="btn button-default post-button"
:disabled="posting"
@click.prevent="postAnnouncement"
>
{{ $t('announcements.post_action') }}
</button>
<div
v-if="error"
class="alert error"
>
{{ $t('announcements.post_error', { error }) }}
<button
class="button-unstyled"
@click="clearError"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="times"
:title="$t('announcements.close_error')"
/>
</button>
</div>
</div>
</div>
</section>
<section <section
v-for="announcement in announcements" v-for="announcement in announcements"
:key="announcement.id" :key="announcement.id"

View file

@ -16,7 +16,7 @@ const WhoToFollow = {
methods: { methods: {
showWhoToFollow (reply) { showWhoToFollow (reply) {
reply.forEach((i, index) => { reply.forEach((i, index) => {
this.$store.state.api.backendInteractor.fetchUser({ id: i.acct }) this.$store.state.api.backendInteractor.fetchUser({ id: i.id })
.then((externalUser) => { .then((externalUser) => {
if (!externalUser.error) { if (!externalUser.error) {
this.$store.commit('addNewUsers', [externalUser]) this.$store.commit('addNewUsers', [externalUser])

View file

@ -9,11 +9,12 @@ function showWhoToFollow (panel, reply) {
let user = shuffled[index] let user = shuffled[index]
let img = user.avatar || this.$store.state.instance.defaultAvatar let img = user.avatar || this.$store.state.instance.defaultAvatar
let name = user.acct let name = user.acct
let id = user.id
toFollow.img = img toFollow.img = img
toFollow.name = name toFollow.name = name
panel.$store.state.api.backendInteractor.fetchUser({ id: name }) panel.$store.state.api.backendInteractor.fetchUser({ id })
.then((externalUser) => { .then((externalUser) => {
if (!externalUser.error) { if (!externalUser.error) {
panel.$store.commit('addNewUsers', [externalUser]) panel.$store.commit('addNewUsers', [externalUser])

View file

@ -48,7 +48,6 @@ const announcements = {
return store.rootState.api.backendInteractor.fetchAnnouncements() return store.rootState.api.backendInteractor.fetchAnnouncements()
} }
const all = await store.rootState.api.backendInteractor.adminFetchAnnouncements()
const visible = await store.rootState.api.backendInteractor.fetchAnnouncements() const visible = await store.rootState.api.backendInteractor.fetchAnnouncements()
const visibleObject = visible.reduce((a, c) => { const visibleObject = visible.reduce((a, c) => {
a[c.id] = c a[c.id] = c
@ -56,7 +55,7 @@ const announcements = {
}, {}) }, {})
const getWithinVisible = announcement => visibleObject[announcement.id] const getWithinVisible = announcement => visibleObject[announcement.id]
all.forEach(announcement => { visible.forEach(announcement => {
const visibleAnnouncement = getWithinVisible(announcement) const visibleAnnouncement = getWithinVisible(announcement)
if (!visibleAnnouncement) { if (!visibleAnnouncement) {
announcement.inactive = true announcement.inactive = true
@ -65,7 +64,7 @@ const announcements = {
} }
}) })
return all return visible
} }
return getAnnouncements() return getAnnouncements()

View file

@ -35,7 +35,7 @@ const defaultState = {
hideWordFilteredPosts: false, hideWordFilteredPosts: false,
hidePostStats: false, hidePostStats: false,
hideBotIndication: false, hideBotIndication: false,
hideSiteFavicon: false, hideSiteFavicon: true,
hideSiteName: false, hideSiteName: false,
hideUserStats: false, hideUserStats: false,
muteBotStatuses: false, muteBotStatuses: false,
@ -177,22 +177,19 @@ const instance = {
async getCustomEmoji ({ commit, state }) { async getCustomEmoji ({ commit, state }) {
try { try {
const res = await window.fetch('/api/v1/pleroma/emoji') const res = await window.fetch('/api/v1/custom_emojis')
if (res.ok) { if (res.ok) {
const result = await res.json() const result = await res.json()
const values = Array.isArray(result) ? Object.assign({}, ...result) : result const emoji = []
const emoji = Object.entries(values).map(([key, value]) => { for (const emojiobj of result) {
const imageUrl = value.image_url emoji.push({
return { displayText: emojiobj.shortcode,
displayText: key, imageUrl: emojiobj.url,
imageUrl: imageUrl ? state.server + imageUrl : value, tags: emojiobj.category ? [`pack:${emojiobj.category.toLowerCase()}`] : ['pack:custom'],
tags: imageUrl ? value.tags.sort((a, b) => a > b ? 1 : 0) : ['utf'], replacement: `:${emojiobj.shortcode}: `
replacement: `:${key}: ` })
} }
// Technically could use tags but those are kinda useless right now, commit('setInstanceOption', { name: 'customEmoji', value: emoji.sort((a, b) => a.displayText.toLowerCase() > b.displayText.toLowerCase() ? 1 : -1) })
// should have been "pack" field, that would be more useful
}).sort((a, b) => a.displayText.toLowerCase() > b.displayText.toLowerCase() ? 1 : -1)
commit('setInstanceOption', { name: 'customEmoji', value: emoji })
} else { } else {
throw (res) throw (res)
} }

View file

@ -752,9 +752,9 @@ const statuses = {
) )
}, },
fetchEmojiReactionsBy ({ rootState, commit }, id) { fetchEmojiReactionsBy ({ rootState, commit }, id) {
rootState.api.backendInteractor.fetchEmojiReactions({ id }).then( rootState.api.backendInteractor.fetchStatus({ id }).then(
emojiReactions => { status => {
commit('addEmojiReactionsBy', { id, emojiReactions, currentUser: rootState.users.currentUser }) commit('addEmojiReactionsBy', { id, emojiReactions: status.emoji_reactions, currentUser: rootState.users.currentUser })
} }
) )
}, },

View file

@ -20,7 +20,7 @@ const ADMIN_USERS_URL = '/api/v1/pleroma/admin/users'
const SUGGESTIONS_URL = '/api/v1/suggestions' const SUGGESTIONS_URL = '/api/v1/suggestions'
const NOTIFICATION_SETTINGS_URL = '/api/pleroma/notification_settings' const NOTIFICATION_SETTINGS_URL = '/api/pleroma/notification_settings'
const NOTIFICATION_READ_URL = '/api/v1/pleroma/notifications/read' const NOTIFICATION_READ_URL = '/api/v1/pleroma/notifications/read'
const ADMIN_REPORTS_URL = '/api/v1/pleroma/admin/reports' const ADMIN_REPORTS_URL = '/api/v1/admin/reports'
const ADMIN_REPORT_NOTES_URL = id => `/api/v1/pleroma/admin/reports/${id}/notes` const ADMIN_REPORT_NOTES_URL = id => `/api/v1/pleroma/admin/reports/${id}/notes`
const ADMIN_REPORT_NOTE_URL = (report, note) => `/api/v1/pleroma/admin/reports/${report}/notes/${note}` const ADMIN_REPORT_NOTE_URL = (report, note) => `/api/v1/pleroma/admin/reports/${report}/notes/${note}`
@ -99,9 +99,9 @@ const MASTODON_STREAMING = '/api/v1/streaming'
const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers' const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
const MASTODON_ANNOUNCEMENTS_URL = '/api/v1/announcements' const MASTODON_ANNOUNCEMENTS_URL = '/api/v1/announcements'
const MASTODON_ANNOUNCEMENTS_DISMISS_URL = id => `/api/v1/announcements/${id}/dismiss` const MASTODON_ANNOUNCEMENTS_DISMISS_URL = id => `/api/v1/announcements/${id}/dismiss`
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions` const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/statuses/${id}/reactions`
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/statuses/${id}/react/${emoji}`
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/statuses/${id}/react/${emoji}`
const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups' const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups'
const PLEROMA_ANNOUNCEMENTS_URL = '/api/v1/pleroma/admin/announcements' const PLEROMA_ANNOUNCEMENTS_URL = '/api/v1/pleroma/admin/announcements'
const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements' const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements'
@ -647,7 +647,7 @@ const getReports = ({ state, limit, page, pageSize, credentials }) => {
url = url + (args ? '?' + args : '') url = url + (args ? '?' + args : '')
return fetch(url, { headers: authHeaders(credentials) }) return fetch(url, { headers: authHeaders(credentials) })
.then((data) => data.json()) .then((data) => data.json())
.then((data) => data?.reports?.map(parseReport) ?? []) .then((data) => data?.map(parseReport) ?? [])
} }
const updateReportStates = ({ credentials, reports }) => { const updateReportStates = ({ credentials, reports }) => {

View file

@ -126,6 +126,34 @@ export const parseUser = (data) => {
} else { } else {
output.role = 'member' output.role = 'member'
} }
} else {
output.relationship = {
muting: [],
blocking: [],
followed_by: [],
following: []
}
output.rights = {
moderator: false,
admin: false
}
// todo: find a better way to map masto roles to akkoma roles
const roles = data.roles
if (roles) {
if (!roles[0]) {
output.role = 'member'
} else if (roles[0].id === "1") {
output.role = 'moderator'
output.rights.moderator = true
} else if (roles[0].id === "2" || roles[0].id === "3") {
output.role = 'admin'
output.rights.admin = true
} else {
output.role = 'member'
}
}
} }
if (data.source) { if (data.source) {
@ -297,6 +325,9 @@ export const parseStatus = (data) => {
} else { } else {
output.text = data.content output.text = data.content
output.summary = data.spoiler_text output.summary = data.spoiler_text
output.emoji_reactions = data.reactions
// todo: properly check if post is visible
output.parent_visible = true
} }
if (data.akkoma) { if (data.akkoma) {
@ -405,14 +436,16 @@ export const parseStatus = (data) => {
export const parseNotification = (data) => { export const parseNotification = (data) => {
const mastoDict = { const mastoDict = {
'favourite': 'like', 'favourite': 'like',
'reblog': 'repeat' 'reblog': 'repeat',
'reaction': 'pleroma:emoji_reaction'
} }
const masto = !data.hasOwnProperty('ntype') const masto = !data.hasOwnProperty('ntype')
const output = {} const output = {}
if (masto) { if (masto) {
output.type = mastoDict[data.type] || data.type output.type = mastoDict[data.type] || data.type
output.seen = data.pleroma.is_seen // todo: figure out how to tell if a notification has been seen or not
output.seen = true
if (data.status) { if (data.status) {
output.status = isStatusNotification(output.type) ? parseStatus(data.status) : null output.status = isStatusNotification(output.type) ? parseStatus(data.status) : null
output.action = output.status // TODO: Refactor, this is unneeded output.action = output.status // TODO: Refactor, this is unneeded
@ -443,15 +476,12 @@ export const parseNotification = (data) => {
export const parseReport = (data) => { export const parseReport = (data) => {
const report = {} const report = {}
report.account = parseUser(data.account) report.account = parseUser(data.target_account.account)
report.actor = parseUser(data.actor) report.actor = parseUser(data.account.account)
report.statuses = data.statuses.map(parseStatus) report.statuses = data.statuses.map(parseStatus)
report.notes = data.notes.map(note => { report.notes = []
note.user = parseUser(note.user) report.state = data.action_taken ? "closed" : "open"
return note report.content = data.comment
})
report.state = data.state
report.content = data.content
report.created_at = data.created_at report.created_at = data.created_at
report.id = data.id report.id = data.id

View file

@ -10,9 +10,9 @@ export const getOrCreateApp = ({ clientId, clientSecret, instance, commit }) =>
const url = `${instance}/api/v1/apps` const url = `${instance}/api/v1/apps`
const form = new window.FormData() const form = new window.FormData()
form.append('client_name', `PleromaFE_${window.___pleromafe_commit_hash}_${(new Date()).toISOString()}`) form.append('client_name', "AkkomaFE")
form.append('redirect_uris', REDIRECT_URI) form.append('redirect_uris', REDIRECT_URI)
form.append('scopes', 'read write follow push admin') form.append('scopes', 'read write follow push admin:read admin:write')
return window.fetch(url, { return window.fetch(url, {
method: 'POST', method: 'POST',
@ -28,7 +28,7 @@ const login = ({ instance, clientId }) => {
response_type: 'code', response_type: 'code',
client_id: clientId, client_id: clientId,
redirect_uri: REDIRECT_URI, redirect_uri: REDIRECT_URI,
scope: 'read write follow push admin' scope: 'read write follow push admin:read admin:write'
} }
const dataString = reduce(data, (acc, v, k) => { const dataString = reduce(data, (acc, v, k) => {

View file

@ -1,6 +1,6 @@
{ {
"alwaysShowSubjectInput": true, "alwaysShowSubjectInput": true,
"background": "/static/aurora_borealis.jpg", "background": "/static/wdwskyboxbanner.png",
"collapseMessageWithSubject": false, "collapseMessageWithSubject": false,
"greentext": false, "greentext": false,
"hideFilteredStatuses": false, "hideFilteredStatuses": false,
@ -8,15 +8,15 @@
"hidePostStats": false, "hidePostStats": false,
"hideSitename": false, "hideSitename": false,
"hideUserStats": false, "hideUserStats": false,
"loginMethod": "password", "loginMethod": "token",
"logo": "/static/logo.svg", "logo": "/static/logo.png",
"logoMargin": ".1em", "logoMargin": ".1em",
"logoMask": true, "logoMask": false,
"logoLeft": false, "logoLeft": false,
"nsfwCensorImage": "", "nsfwCensorImage": "",
"postContentType": "text/plain", "postContentType": "text/plain",
"redirectRootLogin": "/main/friends", "redirectRootLogin": "/main/friends",
"redirectRootNoLogin": "/main/all", "redirectRootNoLogin": "/main/public",
"showFeaturesPanel": true, "showFeaturesPanel": true,
"showInstanceSpecificPanel": false, "showInstanceSpecificPanel": false,
"sidebarRight": false, "sidebarRight": false,

BIN
static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -1,5 +1,3 @@
<h4>Terms of Service</h4> <p>This is Akkoma-FE modified to work on top of Mastodon/Chuckya. Note that while most of it should work fine, there are still a few differences between Akkoma and Mastodon that may cause things to break.<p>
<p>This is a placeholder, overwrite this by putting a file at <pre>$STATIC_DIR/static/terms-of-service.html</pre><p> <p>Source code: <a href="https://akkoma.dev/esm/akkoma-fe">https://akkoma.dev/esm/akkoma-fe</a></p>
<p>See the <a href="https://docs.akkoma.dev/main/backend/configuration/static_dir/">Static Directory</a> docs for more info.</p>

BIN
static/wdwskyboxbanner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB