merge upstream
This commit is contained in:
commit
7e42d667bc
20 changed files with 188 additions and 23 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -10,3 +10,5 @@ config/local.json
|
||||||
config/local.*.json
|
config/local.*.json
|
||||||
docs/site/
|
docs/site/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
tools/.venv/
|
||||||
|
static/ruffle/
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
- script to get new emojis is included for future unicode versions
|
- script to get new emojis is included for future unicode versions
|
||||||
- add toggle for showing post edit notifications
|
- add toggle for showing post edit notifications
|
||||||
- add support for accepted follow request 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`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,9 @@ const conversation = {
|
||||||
streamingEnabled () {
|
streamingEnabled () {
|
||||||
return this.mergedConfig.useStreamingApi && this.mastoUserSocketStatus === WSConnectionStatus.JOINED
|
return this.mergedConfig.useStreamingApi && this.mastoUserSocketStatus === WSConnectionStatus.JOINED
|
||||||
},
|
},
|
||||||
|
timelineStyle () {
|
||||||
|
return this.$store.getters.mergedConfig.timelineStyle
|
||||||
|
},
|
||||||
displayStyle () {
|
displayStyle () {
|
||||||
return this.$store.getters.mergedConfig.conversationDisplay
|
return this.$store.getters.mergedConfig.conversationDisplay
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@
|
||||||
:in-profile="inProfile"
|
:in-profile="inProfile"
|
||||||
:profile-user-id="profileUserId"
|
:profile-user-id="profileUserId"
|
||||||
class="conversation-status status-fadein panel-body"
|
class="conversation-status status-fadein panel-body"
|
||||||
|
:class="timelineStyle"
|
||||||
|
|
||||||
:simple-tree="treeViewIsSimple"
|
:simple-tree="treeViewIsSimple"
|
||||||
:toggle-thread-display="toggleThreadDisplay"
|
:toggle-thread-display="toggleThreadDisplay"
|
||||||
|
|
@ -173,6 +174,7 @@
|
||||||
:in-profile="inProfile"
|
:in-profile="inProfile"
|
||||||
:profile-user-id="profileUserId"
|
:profile-user-id="profileUserId"
|
||||||
class="conversation-status status-fadein panel-body"
|
class="conversation-status status-fadein panel-body"
|
||||||
|
:class="timelineStyle"
|
||||||
|
|
||||||
:toggle-thread-display="toggleThreadDisplay"
|
:toggle-thread-display="toggleThreadDisplay"
|
||||||
:thread-display-status="threadDisplayStatus"
|
:thread-display-status="threadDisplayStatus"
|
||||||
|
|
@ -243,7 +245,7 @@
|
||||||
padding: var(--status-margin, $status-margin);
|
padding: var(--status-margin, $status-margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversation-status {
|
.conversation-status.classic {
|
||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
border-bottom-color: var(--border, $fallback--border);
|
border-bottom-color: var(--border, $fallback--border);
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,9 @@ const EmojiReactions = {
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
},
|
},
|
||||||
|
timelineStyle () {
|
||||||
|
return this.$store.getters.mergedConfig.timelineStyle
|
||||||
|
},
|
||||||
loggedIn () {
|
loggedIn () {
|
||||||
return !!this.$store.state.users.currentUser
|
return !!this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="emoji-reactions">
|
<div class="emoji-reactions" :class="timelineStyle">
|
||||||
<UserListPopover
|
<UserListPopover
|
||||||
v-for="(reaction) in filteredReactions"
|
v-for="(reaction) in filteredReactions"
|
||||||
:key="reaction.url || reaction.name"
|
:key="reaction.url || reaction.name"
|
||||||
|
|
@ -47,8 +47,19 @@
|
||||||
@import '../../_variables.scss';
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
.emoji-reactions {
|
.emoji-reactions {
|
||||||
display: flex;
|
&.classic {
|
||||||
margin-top: 0.25em;
|
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;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
}
|
}
|
||||||
|
|
@ -100,6 +111,7 @@
|
||||||
border: 1px solid var(--accent, $fallback--link);
|
border: 1px solid var(--accent, $fallback--link);
|
||||||
margin-left: -1px; // offset the border, can't use inset shadows either
|
margin-left: -1px; // offset the border, can't use inset shadows either
|
||||||
margin-right: calc(0.5em - 1px);
|
margin-right: calc(0.5em - 1px);
|
||||||
|
box-shadow: 0 0 4px 4px rgba(255,255,255,.5) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,9 @@ const Notification = {
|
||||||
user () {
|
user () {
|
||||||
return this.$store.getters.findUser(this.notification.from_profile.id)
|
return this.$store.getters.findUser(this.notification.from_profile.id)
|
||||||
},
|
},
|
||||||
|
timelineStyle () {
|
||||||
|
return this.$store.getters.mergedConfig.timelineStyle
|
||||||
|
},
|
||||||
userProfileLink () {
|
userProfileLink () {
|
||||||
return this.generateUserProfileLink(this.user)
|
return this.generateUserProfileLink(this.user)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
<Status
|
<Status
|
||||||
v-if="notification.type === 'mention'"
|
v-if="notification.type === 'mention'"
|
||||||
class="Notification"
|
class="Notification"
|
||||||
|
:class="timelineStyle"
|
||||||
:compact="true"
|
:compact="true"
|
||||||
:statusoid="notification.status"
|
:statusoid="notification.status"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
z-index: 500;
|
z-index: 500;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
filter: drop-shadow(1px 1px 4px rgba(0,0,0,0.6));
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover-default {
|
.popover-default {
|
||||||
|
|
@ -53,8 +54,6 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
|
|
||||||
box-shadow: var(--panelShadow);
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@ const QuoteCard = {
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
'mergedConfig'
|
'mergedConfig'
|
||||||
])
|
]),
|
||||||
|
timelineStyle () {
|
||||||
|
return this.$store.getters.mergedConfig.timelineStyle
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
QuoteCardContent
|
QuoteCardContent
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
<div>
|
<div>
|
||||||
<router-link
|
<router-link
|
||||||
class="quote-card"
|
class="quote-card"
|
||||||
|
:class="timelineStyle"
|
||||||
:to="{ name: 'conversation', params: { id: status.id } }"
|
:to="{ name: 'conversation', params: { id: status.id } }"
|
||||||
>
|
>
|
||||||
<QuoteCardContent
|
<QuoteCardContent
|
||||||
|
|
@ -23,6 +24,10 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-top: 0.5em;
|
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 {
|
.card-image {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
|
|
@ -64,11 +69,14 @@
|
||||||
|
|
||||||
color: $fallback--text;
|
color: $fallback--text;
|
||||||
color: var(--text, $fallback--text);
|
color: var(--text, $fallback--text);
|
||||||
|
|
||||||
|
&.classic {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-radius: $fallback--attachmentRadius;
|
border-radius: $fallback--attachmentRadius;
|
||||||
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
|
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
|
||||||
border-color: $fallback--border;
|
border-color: $fallback--border;
|
||||||
border-color: var(--border, $fallback--border);
|
border-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,11 @@ const GeneralTab = {
|
||||||
value: tab,
|
value: tab,
|
||||||
label: this.$t(`user_card.${tab}`)
|
label: this.$t(`user_card.${tab}`)
|
||||||
})),
|
})),
|
||||||
|
timelineStyleOptions: ['classic', 'chostlike'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.timeline_${mode}`)
|
||||||
|
})),
|
||||||
profilesExpanded: false,
|
profilesExpanded: false,
|
||||||
newProfileName: '',
|
newProfileName: '',
|
||||||
loopSilentAvailable:
|
loopSilentAvailable:
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,15 @@
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.interface') }}</h2>
|
<h2>{{ $t('settings.interface') }}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
id="timelineStyle"
|
||||||
|
path="timelineStyle"
|
||||||
|
:options="timelineStyleOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.timeline_style_choice') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
<li v-if="instanceSpecificPanelPresent">
|
<li v-if="instanceSpecificPanelPresent">
|
||||||
<BooleanSetting path="hideISP">
|
<BooleanSetting path="hideISP">
|
||||||
{{ $t('settings.hide_isp') }}
|
{{ $t('settings.hide_isp') }}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
.status-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: var(--status-margin, $status-margin);
|
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
@ -104,7 +167,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-heading {
|
.status-heading {
|
||||||
margin-bottom: 0.5em;
|
|
||||||
|
|
||||||
.emoji {
|
.emoji {
|
||||||
--emoji-size: 16px;
|
--emoji-size: 16px;
|
||||||
|
|
@ -244,7 +307,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.replies {
|
.replies {
|
||||||
margin-top: 0.25em;
|
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,9 @@ const ThreadTree = {
|
||||||
return table
|
return table
|
||||||
}, {})
|
}, {})
|
||||||
},
|
},
|
||||||
|
timelineStyle () {
|
||||||
|
return this.$store.getters.mergedConfig.timelineStyle
|
||||||
|
},
|
||||||
currentReplies () {
|
currentReplies () {
|
||||||
return this.getReplies(this.status.id).map(({ id }) => this.statusById(id))
|
return this.getReplies(this.status.id).map(({ id }) => this.statusById(id))
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
:in-profile="inProfile"
|
:in-profile="inProfile"
|
||||||
:profile-user-id="profileUserId"
|
:profile-user-id="profileUserId"
|
||||||
class="conversation-status conversation-status-treeview status-fadein panel-body"
|
class="conversation-status conversation-status-treeview status-fadein panel-body"
|
||||||
|
:class="timelineStyle"
|
||||||
|
|
||||||
:simple-tree="simple"
|
:simple-tree="simple"
|
||||||
:controlled-thread-display-status="threadDisplayStatus[status.id]"
|
:controlled-thread-display-status="threadDisplayStatus[status.id]"
|
||||||
|
|
|
||||||
|
|
@ -957,6 +957,9 @@
|
||||||
"third_column_mode_none": "Don't show third column at all",
|
"third_column_mode_none": "Don't show third column at all",
|
||||||
"third_column_mode_notifications": "Notifications column",
|
"third_column_mode_notifications": "Notifications column",
|
||||||
"third_column_mode_postform": "Main post form and navigation",
|
"third_column_mode_postform": "Main post form and navigation",
|
||||||
|
"timeline_classic": "Classic",
|
||||||
|
"timeline_chostlike": "Cohost-like",
|
||||||
|
"timeline_style_choice": "Timeline post style",
|
||||||
"token": "Token",
|
"token": "Token",
|
||||||
"tooltipRadius": "Tooltips/alerts",
|
"tooltipRadius": "Tooltips/alerts",
|
||||||
"translation_language": "Automatic Translation Language",
|
"translation_language": "Automatic Translation Language",
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ export const defaultState = {
|
||||||
postLanguage: undefined, // instance default,
|
postLanguage: undefined, // instance default,
|
||||||
supportedTranslationLanguages: {}, // instance default
|
supportedTranslationLanguages: {}, // instance default
|
||||||
userProfileDefaultTab: 'statuses',
|
userProfileDefaultTab: 'statuses',
|
||||||
|
timelineStyle: 'classic',
|
||||||
useBlurhash: true,
|
useBlurhash: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,8 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
let retweet
|
let retweet
|
||||||
// If the retweeted status is already there, don't add the retweet
|
// If the retweeted status is already there, don't add the retweet
|
||||||
// to the timeline.
|
// 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) {
|
if (s.retweeted_status) {
|
||||||
return s.id === retweetedStatus.id || s.retweeted_status.id === retweetedStatus.id
|
return s.id === retweetedStatus.id || s.retweeted_status.id === retweetedStatus.id
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
42
tools/download_ruffle.py
Normal file
42
tools/download_ruffle.py
Normal 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")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue