diff --git a/index.html b/index.html
index 781b0ba3..5b684594 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,6 @@
Akkoma
-
diff --git a/src/App.js b/src/App.js
index 3e0d0d6f..77b40b62 100644
--- a/src/App.js
+++ b/src/App.js
@@ -59,7 +59,8 @@ export default {
{
'-reverse': this.reverseLayout,
'-no-sticky-headers': this.noSticky,
- '-has-new-post-button': this.newPostButtonShown
+ '-has-new-post-button': this.newPostButtonShown,
+ '-wide-timeline': this.widenTimeline
},
'-' + this.layoutType
]
@@ -93,6 +94,9 @@ export default {
newPostButtonShown () {
return this.$store.getters.mergedConfig.alwaysShowNewPostButton || this.layoutType === 'mobile'
},
+ widenTimeline () {
+ return this.$store.getters.mergedConfig.widenTimeline
+ },
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
editingAvailable () { return this.$store.state.instance.editingAvailable },
layoutType () { return this.$store.state.interface.layoutType },
diff --git a/src/App.scss b/src/App.scss
index 1d338d15..11d808d6 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -172,6 +172,10 @@ nav {
background-color: rgba(0, 0, 0, 0.15);
background-color: var(--underlay, rgba(0, 0, 0, 0.15));
z-index: -1000;
+
+ .-wide-timeline & {
+ margin:0 calc(var(--columnGap) / -2);
+ }
}
.app-layout {
@@ -187,12 +191,17 @@ nav {
grid-template-rows: 1fr;
box-sizing: border-box;
margin: 0 auto;
+ padding: 0 calc(var(--columnGap) / 2);
align-content: flex-start;
flex-wrap: wrap;
justify-content: center;
min-height: 100vh;
overflow-x: clip;
+ &.-wide-timeline {
+ --maxiColumn: minmax(var(--miniColumn), 1fr);
+ }
+
.column {
--___columnMargin: var(--columnGap);
diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js
index a0778b6d..58b14967 100644
--- a/src/components/emoji_input/suggestor.js
+++ b/src/components/emoji_input/suggestor.js
@@ -1,4 +1,4 @@
-const MFM_TAGS = ['blur', 'bounce', 'flip', 'font', 'jelly', 'jump', 'rainbow', 'rotate', 'shake', 'sparkle', 'spin', 'tada', 'twitch', 'x2', 'x3', 'x4']
+const MFM_TAGS = ['bg', 'blur', 'bounce', 'center', 'fg', 'flip', 'font', 'jelly', 'jump', 'position', 'rainbow', 'rotate', 'scale', 'shake', 'sparkle', 'spin', 'tada', 'twitch', 'x2', 'x3', 'x4']
.map(tag => ({ displayText: tag, detailText: '$[' + tag + ' ]', replacement: '$[' + tag + ' ]', mfm: true }))
/**
diff --git a/src/components/gallery/gallery.js b/src/components/gallery/gallery.js
index 4e1bda55..fa3ec72f 100644
--- a/src/components/gallery/gallery.js
+++ b/src/components/gallery/gallery.js
@@ -88,10 +88,8 @@ const Gallery = {
set(this.sizes, id, { width, height })
},
rowStyle (row) {
- if (row.audio) {
- return { 'padding-bottom': '25%' } // fixed reduced height for audio
- } else if (!row.minimal && !row.grid) {
- return { 'padding-bottom': `${(100 / (row.items.length + 0.6))}%` }
+ if (!row.audio && !row.minimal && !row.grid) {
+ return { 'aspect-ratio': `1/${(1 / (row.items.length + 0.6))}` }
}
},
itemStyle (id, row) {
diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue
index d5500334..13f154e7 100644
--- a/src/components/gallery/gallery.vue
+++ b/src/components/gallery/gallery.vue
@@ -96,9 +96,15 @@
.gallery-row {
position: relative;
- height: 0;
width: 100%;
flex-grow: 1;
+ .Status & {
+ max-height: 10em;
+ }
+
+ &.-audio {
+ aspect-ratio: 4/1; // this is terrible, but it's how it was before so I'm not changing it >:(
+ }
&:not(:first-child) {
margin-top: 0.5em;
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index 0da7f3de..eeb5475e 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -121,6 +121,19 @@ export default {
}
}
+ const mfmStyleFromDataAttributes = (attributes) => {
+ // CSS selectors can check if a data-* attribute is true, but can't use other values, so we want to add them to the style attribute
+ // Here we turn e.g. `{'data-mfm-some': '1deg', 'data-mfm-thing': '5s'}` to "--mfm-some: 1deg;--mfm-thing: 5s;"
+ // Note that we only add the value to `style` when they contain only letters, numbers, dot, or minus signs
+ // At the moment of writing, this should be enough for legitimate purposes and reduces the chance of injection by using special characters
+ // There is a special case for the `color` value, who is provided without `#`, but requires this in the `style` attribute
+ return Object.keys(attributes).filter(
+ (key) => key.startsWith('data-mfm-') && attributes[key] !== true && /^[a-zA-Z0-9.\-]*$/.test(attributes[key])
+ ).map(
+ (key) => '--mfm-' + key.substr(9) + (key === 'data-mfm-color' ? ': #' : ': ') + attributes[key] + ';'
+ ).reduce((a,v) => a+v, '')
+ }
+
// Processor to use with html_tree_converter
const processItem = (item, index, array, what) => {
// Handle text nodes - just add emoji
@@ -191,6 +204,15 @@ export default {
if (this.handleLinks && attrs?.['class']?.includes?.('h-card')) {
return ['', children.map(processItem), '']
}
+
+ let mfm_style = mfmStyleFromDataAttributes(attrs)
+ if (mfm_style !== '') {
+ return [
+ opener.slice(0,-1) + ' style="' + mfm_style + '">',
+ children.map(processItem),
+ closer
+ ]
+ }
}
if (children !== undefined) {
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 4f314ca0..fde41a60 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -159,6 +159,16 @@
{{ $t('settings.show_page_backgrounds') }}
+
+
+ {{ $t('settings.center_align_bio') }}
+
+
+
+
+ {{ $t('settings.compact_user_info') }}
+
+
{{ $t('settings.stop_gifs') }}
@@ -269,6 +279,11 @@
{{ $t('settings.right_sidebar') }}
+
+
+ {{ $t('settings.widen_timeline') }}
+
+