mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-25 04:53:10 +02:00
Compare commits
48 commits
ac7525c4fe
...
f2d059115c
Author | SHA1 | Date | |
---|---|---|---|
|
f2d059115c | ||
|
e0afeff248 | ||
|
cfc8081cec | ||
|
011ccd3a9a | ||
|
28065fc1d1 | ||
|
960f4fcff7 | ||
|
92eec2178f | ||
|
56dca6dbf5 | ||
|
2a634e0309 | ||
|
e6970a0e7c | ||
|
571272a564 | ||
|
30bb0f60a2 | ||
|
328546c4cd | ||
|
f4e89f2e6b | ||
|
2cad97c1ab | ||
|
6ecfe7c7c3 | ||
|
23f476dbf3 | ||
|
7a1251423f | ||
|
7f5492a395 | ||
|
e74ff698c9 | ||
|
11d9fd9199 | ||
|
6132bc3b3e | ||
|
fef7a7b99a | ||
|
1948ca9aa8 | ||
|
848e1f9a56 | ||
|
9c4353ee79 | ||
|
a6e257f502 | ||
|
310e1a1262 | ||
|
15f3c046d1 | ||
|
01d695428a | ||
|
acf3e3460f | ||
|
4c8116859c | ||
|
0e13397db7 | ||
|
ad8818508f | ||
|
d444ee662f | ||
|
4c354fff2d | ||
|
b81448edf6 | ||
|
134d2895f0 | ||
|
7ba8fde9b9 | ||
|
1022280465 | ||
|
021d3924e6 | ||
|
b6d50d781f | ||
|
1d411bb885 | ||
|
f7afd1ae4a | ||
|
1ef1f2a03c | ||
|
829ce4f86a | ||
|
6d5d863150 | ||
|
fc7d4bc420 |
10 changed files with 47 additions and 11 deletions
|
@ -55,6 +55,8 @@ getImageTag:
|
||||||
only:
|
only:
|
||||||
- stable
|
- stable
|
||||||
- develop
|
- develop
|
||||||
|
- tags
|
||||||
|
|
||||||
buildDocker:
|
buildDocker:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
needs:
|
needs:
|
||||||
|
@ -78,6 +80,8 @@ buildDocker:
|
||||||
only:
|
only:
|
||||||
- stable
|
- stable
|
||||||
- develop
|
- develop
|
||||||
|
- tags
|
||||||
|
|
||||||
mergeManifests:
|
mergeManifests:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
needs:
|
needs:
|
||||||
|
@ -103,3 +107,4 @@ mergeManifests:
|
||||||
only:
|
only:
|
||||||
- stable
|
- stable
|
||||||
- develop
|
- develop
|
||||||
|
- tags
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "sharkey",
|
"name": "sharkey",
|
||||||
"version": "2024.3.1",
|
"version": "2024.3.2-devel",
|
||||||
"codename": "shonk",
|
"codename": "shonk",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -172,7 +172,7 @@
|
||||||
"stringz": "2.1.0",
|
"stringz": "2.1.0",
|
||||||
"systeminformation": "5.22.0",
|
"systeminformation": "5.22.0",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
"tmp": "0.2.2",
|
"tmp": "0.2.3",
|
||||||
"tsc-alias": "1.8.8",
|
"tsc-alias": "1.8.8",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typeorm": "0.3.20",
|
"typeorm": "0.3.20",
|
||||||
|
|
|
@ -192,6 +192,7 @@ export class FileServerService {
|
||||||
reply.header('Content-Range', `bytes ${start}-${end}/${file.file.size}`);
|
reply.header('Content-Range', `bytes ${start}-${end}/${file.file.size}`);
|
||||||
reply.header('Accept-Ranges', 'bytes');
|
reply.header('Accept-Ranges', 'bytes');
|
||||||
reply.header('Content-Length', chunksize);
|
reply.header('Content-Length', chunksize);
|
||||||
|
reply.code(206);
|
||||||
} else {
|
} else {
|
||||||
image = {
|
image = {
|
||||||
data: fs.createReadStream(file.path),
|
data: fs.createReadStream(file.path),
|
||||||
|
@ -261,7 +262,6 @@ export class FileServerService {
|
||||||
const parts = range.replace(/bytes=/, '').split('-');
|
const parts = range.replace(/bytes=/, '').split('-');
|
||||||
const start = parseInt(parts[0], 10);
|
const start = parseInt(parts[0], 10);
|
||||||
let end = parts[1] ? parseInt(parts[1], 10) : file.file.size - 1;
|
let end = parts[1] ? parseInt(parts[1], 10) : file.file.size - 1;
|
||||||
console.log(end);
|
|
||||||
if (end > file.file.size) {
|
if (end > file.file.size) {
|
||||||
end = file.file.size - 1;
|
end = file.file.size - 1;
|
||||||
}
|
}
|
||||||
|
@ -431,6 +431,7 @@ export class FileServerService {
|
||||||
reply.header('Content-Range', `bytes ${start}-${end}/${file.file.size}`);
|
reply.header('Content-Range', `bytes ${start}-${end}/${file.file.size}`);
|
||||||
reply.header('Accept-Ranges', 'bytes');
|
reply.header('Accept-Ranges', 'bytes');
|
||||||
reply.header('Content-Length', chunksize);
|
reply.header('Content-Length', chunksize);
|
||||||
|
reply.code(206);
|
||||||
} else {
|
} else {
|
||||||
image = {
|
image = {
|
||||||
data: fs.createReadStream(file.path),
|
data: fs.createReadStream(file.path),
|
||||||
|
@ -527,6 +528,9 @@ export class FileServerService {
|
||||||
if (!file.storedInternal) {
|
if (!file.storedInternal) {
|
||||||
if (!(file.isLink && file.uri)) return '204';
|
if (!(file.isLink && file.uri)) return '204';
|
||||||
const result = await this.downloadAndDetectTypeFromUrl(file.uri);
|
const result = await this.downloadAndDetectTypeFromUrl(file.uri);
|
||||||
|
if (!file.size) {
|
||||||
|
file.size = (await fs.promises.stat(result.path)).size;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
url: file.uri,
|
url: file.uri,
|
||||||
|
|
|
@ -5,8 +5,8 @@ block vars
|
||||||
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
|
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
|
||||||
- const url = `${config.url}/notes/${note.id}`;
|
- const url = `${config.url}/notes/${note.id}`;
|
||||||
- const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null;
|
- const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null;
|
||||||
- const images = (note.files || []).filter(file => file.type.startsWith('image/') && !file.isSensitive)
|
- const images = note.cw ? [] : (note.files || []).filter(file => file.type.startsWith('image/') && !file.isSensitive)
|
||||||
- const videos = (note.files || []).filter(file => file.type.startsWith('video/') && !file.isSensitive)
|
- const videos = note.cw ? [] : (note.files || []).filter(file => file.type.startsWith('video/') && !file.isSensitive)
|
||||||
|
|
||||||
block title
|
block title
|
||||||
= `${title} | ${instanceName}`
|
= `${title} | ${instanceName}`
|
||||||
|
|
|
@ -178,7 +178,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div v-if="!repliesLoaded" style="padding: 16px">
|
<div v-if="!repliesLoaded" style="padding: 16px">
|
||||||
<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
|
<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<SkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="true"/>
|
<SkNoteSub v-for="note in sortedReplies" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="true"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
|
<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
|
||||||
<MkPagination :pagination="renotesPagination" :disableAutoLoad="true">
|
<MkPagination :pagination="renotesPagination" :disableAutoLoad="true">
|
||||||
|
@ -266,6 +266,7 @@ import MkPagination, { type Paging } from '@/components/MkPagination.vue';
|
||||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
|
import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
|
||||||
|
import { sortReplies } from '@/scripts/reply-sorting.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
note: Misskey.entities.Note;
|
note: Misskey.entities.Note;
|
||||||
|
@ -327,6 +328,7 @@ const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.anima
|
||||||
const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.value.user.instance);
|
const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.value.user.instance);
|
||||||
const conversation = ref<Misskey.entities.Note[]>([]);
|
const conversation = ref<Misskey.entities.Note[]>([]);
|
||||||
const replies = ref<Misskey.entities.Note[]>([]);
|
const replies = ref<Misskey.entities.Note[]>([]);
|
||||||
|
const sortedReplies = computed(() => sortReplies(props.note, replies.value));
|
||||||
const quotes = ref<Misskey.entities.Note[]>([]);
|
const quotes = ref<Misskey.entities.Note[]>([]);
|
||||||
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
|
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
|
||||||
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
||||||
|
|
|
@ -73,7 +73,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="depth < numberOfReplies">
|
<template v-if="depth < numberOfReplies">
|
||||||
<SkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="props.isReply"/>
|
<SkNoteSub v-for="reply in sortedReplies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="props.isReply"/>
|
||||||
</template>
|
</template>
|
||||||
<div v-else :class="$style.more">
|
<div v-else :class="$style.more">
|
||||||
<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ph-caret-double-right ph-bold ph-lg"></i></MkA>
|
<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ph-caret-double-right ph-bold ph-lg"></i></MkA>
|
||||||
|
@ -114,6 +114,7 @@ import { claimAchievement } from '@/scripts/achievements.js';
|
||||||
import { getNoteMenu } from '@/scripts/get-note-menu.js';
|
import { getNoteMenu } from '@/scripts/get-note-menu.js';
|
||||||
import { useNoteCapture } from '@/scripts/use-note-capture.js';
|
import { useNoteCapture } from '@/scripts/use-note-capture.js';
|
||||||
import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
|
import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
|
||||||
|
import { sortReplies } from '@/scripts/reply-sorting.js';
|
||||||
|
|
||||||
const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
|
const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
|
||||||
const hideLine = computed(() => { return props.detail ? true : false; });
|
const hideLine = computed(() => { return props.detail ? true : false; });
|
||||||
|
@ -151,6 +152,7 @@ const likeButton = shallowRef<HTMLElement>();
|
||||||
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
|
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
|
||||||
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
||||||
const replies = ref<Misskey.entities.Note[]>([]);
|
const replies = ref<Misskey.entities.Note[]>([]);
|
||||||
|
const sortedReplies = computed(() => sortReplies(props.note, replies.value));
|
||||||
|
|
||||||
const isRenote = (
|
const isRenote = (
|
||||||
props.note.renote != null &&
|
props.note.renote != null &&
|
||||||
|
|
17
packages/frontend/src/scripts/reply-sorting.ts
Normal file
17
packages/frontend/src/scripts/reply-sorting.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import * as Misskey from 'misskey-js';
|
||||||
|
|
||||||
|
// sorts replies to self before other replies to make threads easier to read
|
||||||
|
export function sortReplies(root: Misskey.entities.Note, replies: Misskey.entities.Note[]): Misskey.entities.Note[] {
|
||||||
|
const result: Misskey.entities.Note[] = [];
|
||||||
|
|
||||||
|
for (const reply of replies) {
|
||||||
|
if (root.userId === reply.userId) {
|
||||||
|
result.unshift(reply);
|
||||||
|
} else {
|
||||||
|
result.push(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -392,8 +392,8 @@ importers:
|
||||||
specifier: 1.6.0
|
specifier: 1.6.0
|
||||||
version: 1.6.0
|
version: 1.6.0
|
||||||
tmp:
|
tmp:
|
||||||
specifier: 0.2.2
|
specifier: 0.2.3
|
||||||
version: 0.2.2
|
version: 0.2.3
|
||||||
tsc-alias:
|
tsc-alias:
|
||||||
specifier: 1.8.8
|
specifier: 1.8.8
|
||||||
version: 1.8.8
|
version: 1.8.8
|
||||||
|
@ -18813,6 +18813,12 @@ packages:
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
dependencies:
|
dependencies:
|
||||||
rimraf: 5.0.5
|
rimraf: 5.0.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/tmp@0.2.3:
|
||||||
|
resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==}
|
||||||
|
engines: {node: '>=14.14'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tmpl@1.0.5:
|
/tmpl@1.0.5:
|
||||||
resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
|
resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
|
||||||
|
|
Loading…
Reference in a new issue