2
0
Fork 0

merge upstream

This commit is contained in:
Ruben 2025-07-30 14:05:32 -05:00
commit 7e42d667bc
Signed by: sneexy
GPG key ID: 8ECFA045E63BC583
20 changed files with 188 additions and 23 deletions

2
.gitignore vendored
View file

@ -10,3 +10,5 @@ config/local.json
config/local.*.json
docs/site/
.vscode/
tools/.venv/
static/ruffle/

View file

@ -33,6 +33,8 @@
- script to get new emojis is included for future unicode versions
- add toggle for showing post edit notifications
- add support for accepted follow request notifications
- add a script to download ruffle for flash support (requires python3 and requests library)
- download by entering `tools/` and running `python3 download_ruffle.py`
---

View file

@ -82,6 +82,9 @@ const conversation = {
streamingEnabled () {
return this.mergedConfig.useStreamingApi && this.mastoUserSocketStatus === WSConnectionStatus.JOINED
},
timelineStyle () {
return this.$store.getters.mergedConfig.timelineStyle
},
displayStyle () {
return this.$store.getters.mergedConfig.conversationDisplay
},

View file

@ -69,6 +69,7 @@
:in-profile="inProfile"
:profile-user-id="profileUserId"
class="conversation-status status-fadein panel-body"
:class="timelineStyle"
:simple-tree="treeViewIsSimple"
:toggle-thread-display="toggleThreadDisplay"
@ -173,6 +174,7 @@
:in-profile="inProfile"
:profile-user-id="profileUserId"
class="conversation-status status-fadein panel-body"
:class="timelineStyle"
:toggle-thread-display="toggleThreadDisplay"
:thread-display-status="threadDisplayStatus"
@ -243,7 +245,7 @@
padding: var(--status-margin, $status-margin);
}
.conversation-status {
.conversation-status.classic {
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: var(--border, $fallback--border);

View file

@ -39,6 +39,9 @@ const EmojiReactions = {
return acc
}, {})
},
timelineStyle () {
return this.$store.getters.mergedConfig.timelineStyle
},
loggedIn () {
return !!this.$store.state.users.currentUser
},

View file

@ -1,5 +1,5 @@
<template>
<div class="emoji-reactions">
<div class="emoji-reactions" :class="timelineStyle">
<UserListPopover
v-for="(reaction) in filteredReactions"
:key="reaction.url || reaction.name"
@ -47,8 +47,19 @@
@import '../../_variables.scss';
.emoji-reactions {
&.classic {
margin-top: 0.25em;
}
&.chostlike {
padding-left: 10px;
padding-right: 10px;
padding-bottom: .5em;
background: var(--bg);
border-bottom: 1px solid var(--faint);
}
display: flex;
margin-top: 0.25em;
flex-wrap: wrap;
container-type: inline-size;
}
@ -100,6 +111,7 @@
border: 1px solid var(--accent, $fallback--link);
margin-left: -1px; // offset the border, can't use inset shadows either
margin-right: calc(0.5em - 1px);
box-shadow: 0 0 4px 4px rgba(255,255,255,.5) inset;
}
</style>

View file

@ -150,6 +150,9 @@ const Notification = {
user () {
return this.$store.getters.findUser(this.notification.from_profile.id)
},
timelineStyle () {
return this.$store.getters.mergedConfig.timelineStyle
},
userProfileLink () {
return this.generateUserProfileLink(this.user)
},

View file

@ -2,6 +2,7 @@
<Status
v-if="notification.type === 'mention'"
class="Notification"
:class="timelineStyle"
:compact="true"
:statusoid="notification.status"
/>

View file

@ -40,6 +40,7 @@
z-index: 500;
position: absolute;
min-width: 0;
filter: drop-shadow(1px 1px 4px rgba(0,0,0,0.6));
}
.popover-default {
@ -53,8 +54,6 @@
left: 0;
right: 0;
z-index: 3;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
box-shadow: var(--panelShadow);
pointer-events: none;
}

View file

@ -14,7 +14,10 @@ const QuoteCard = {
computed: {
...mapGetters([
'mergedConfig'
])
]),
timelineStyle () {
return this.$store.getters.mergedConfig.timelineStyle
},
},
components: {
QuoteCardContent

View file

@ -2,6 +2,7 @@
<div>
<router-link
class="quote-card"
:class="timelineStyle"
:to="{ name: 'conversation', params: { id: status.id } }"
>
<QuoteCardContent
@ -23,6 +24,10 @@
overflow: hidden;
margin-top: 0.5em;
&.chostian .right-side {
background: linear-gradient(180deg, var(--selectedPost, $fallback--lightBg) 0%, var(--selectedPost, $fallback--lightBg) 75%, var(--bg) 75%, var(--bg) 100%) !important;
}
.card-image {
flex-shrink: 0;
width: 120px;
@ -64,11 +69,14 @@
color: $fallback--text;
color: var(--text, $fallback--text);
border-style: solid;
border-width: 1px;
border-radius: $fallback--attachmentRadius;
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
&.classic {
border-style: solid;
border-width: 1px;
border-radius: $fallback--attachmentRadius;
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
}
}
</style>

View file

@ -55,6 +55,11 @@ const GeneralTab = {
value: tab,
label: this.$t(`user_card.${tab}`)
})),
timelineStyleOptions: ['classic', 'chostlike'].map(mode => ({
key: mode,
value: mode,
label: this.$t(`settings.timeline_${mode}`)
})),
profilesExpanded: false,
newProfileName: '',
loopSilentAvailable:

View file

@ -104,6 +104,15 @@
<div class="setting-item">
<h2>{{ $t('settings.interface') }}</h2>
<ul class="setting-list">
<li>
<ChoiceSetting
id="timelineStyle"
path="timelineStyle"
:options="timelineStyleOptions"
>
{{ $t('settings.timeline_style_choice') }}
</ChoiceSetting>
</li>
<li v-if="instanceSpecificPanelPresent">
<BooleanSetting path="hideISP">
{{ $t('settings.hide_isp') }}

View file

@ -38,9 +38,72 @@
}
}
&.classic .status-container {
padding: var(--status-margin, $status-margin);
}
&.classic .status-heading {
margin-bottom: 0.5em;
}
&.classic .replies {
margin-top: 0.25em;
}
&.chostlike .status-container {
padding: calc(10px + var(--status-margin, 0.75em)) var(--status-margin, 0.75em);
.content {
padding-bottom: .5em;
padding-top: 1em;
padding-left: 10px;
padding-right: 10px;
background: var(--bg);
}
.right-side {
background-color: var(--selectedPost);
border-radius: 10px;
padding: 10px 0 10px 0;
box-shadow: #000c 0px 0px 10px;
}
.status-heading {
border-bottom: 1px solid var(--faint);
padding: .3em 1em .7em 1em;
}
.replies {
padding-top: 0.25em;
padding-left: 10px;
padding-right: 10px;
background: var(--bg);
}
&.repeat-info {
padding-top: calc(10px + var(--status-margin, 0.75em));
padding-bottom: 0px;
.right-side {
border-radius: 10px 10px 0 0;
padding-left: 10px;
padding-right: 10px;
border-bottom: 1px solid #0003;
}
}
&.repeat-info + .status-container .right-side {
border-radius: 0px 0px 10px 10px;
}
.status-actions {
padding-left: 10px;
padding-right: 10px;
}
}
.status-container {
display: flex;
padding: var(--status-margin, $status-margin);
.content {
overflow: hidden;
@ -104,7 +167,7 @@
}
.status-heading {
margin-bottom: 0.5em;
.emoji {
--emoji-size: 16px;
@ -244,7 +307,6 @@
}
.replies {
margin-top: 0.25em;
line-height: 1.3;
font-size: 0.85em;
display: flex;

View file

@ -58,6 +58,9 @@ const ThreadTree = {
return table
}, {})
},
timelineStyle () {
return this.$store.getters.mergedConfig.timelineStyle
},
currentReplies () {
return this.getReplies(this.status.id).map(({ id }) => this.statusById(id))
},

View file

@ -14,6 +14,7 @@
:in-profile="inProfile"
:profile-user-id="profileUserId"
class="conversation-status conversation-status-treeview status-fadein panel-body"
:class="timelineStyle"
:simple-tree="simple"
:controlled-thread-display-status="threadDisplayStatus[status.id]"

View file

@ -957,6 +957,9 @@
"third_column_mode_none": "Don't show third column at all",
"third_column_mode_notifications": "Notifications column",
"third_column_mode_postform": "Main post form and navigation",
"timeline_classic": "Classic",
"timeline_chostlike": "Cohost-like",
"timeline_style_choice": "Timeline post style",
"token": "Token",
"tooltipRadius": "Tooltips/alerts",
"translation_language": "Automatic Translation Language",

View file

@ -142,6 +142,7 @@ export const defaultState = {
postLanguage: undefined, // instance default,
supportedTranslationLanguages: {}, // instance default
userProfileDefaultTab: 'statuses',
timelineStyle: 'classic',
useBlurhash: true,
}

View file

@ -261,7 +261,8 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
let retweet
// If the retweeted status is already there, don't add the retweet
// to the timeline.
if (rootState.config.dedupeBoosts && timeline && find(timelineObject.statuses, (s) => {
var cond = rootState !== undefined ? rootState.config.dedupeBoosts : true
if (cond && rootState.config.dedupeBoosts && timeline && find(timelineObject.statuses, (s) => {
if (s.retweeted_status) {
return s.id === retweetedStatus.id || s.retweeted_status.id === retweetedStatus.id
} else {

42
tools/download_ruffle.py Normal file
View file

@ -0,0 +1,42 @@
import requests, json, zipfile, os, glob
if os.path.isdir("../static/ruffle/"):
print("Flash is already downloaded, clearing old directory and updating...")
rm = glob.glob("../static/ruffle/*")
for x in rm:
os.remove(x)
else:
print("Flash is not downloaded yet, creating directory...")
os.mkdir("../static/ruffle/")
releases = requests.get("https://api.github.com/repos/ruffle-rs/ruffle/releases?per_page=1")
releasesJsonified = json.loads(releases.text)
for asset in releasesJsonified[0]["assets"]:
if "web-selfhosted" in asset["browser_download_url"]:
newFlashFiles = requests.get(asset["browser_download_url"])
flashDumped = open("flash.zip", "wb+")
flashDumped.write(newFlashFiles.content)
flashZip = zipfile.ZipFile("flash.zip", "r")
flashZip.extractall("../static/ruffle/")
rmglob = glob.glob("../static/ruffle/*.map")
rm = ["../static/ruffle/README.md",
"../static/ruffle/LICENSE_MIT",
"../static/ruffle/LICENSE_APACHE",
"../static/ruffle/package.json"]
for item in rmglob:
rm.append(item)
for item in rm:
os.remove(item)
flashZip.close()
os.remove("flash.zip")
print("Flash was successfully downloaded and extracted")
exit()
print("Flash not found, download it manually at https://github.com/ruffle-rs/ruffle/releases")