Compare commits

...

2 Commits

Author SHA1 Message Date
Derek 7d8205930a ChatUI modernization part 3 2022-10-19 21:24:32 -04:00
Derek e6a4ee4d62 Merge fixup 2022-10-17 07:11:56 -04:00
5 changed files with 108 additions and 114 deletions

View File

@ -83,4 +83,12 @@ export class Channel {
comment: 'The count of users.', comment: 'The count of users.',
}) })
public usersCount: number; public usersCount: number;
constructor(data: Partial<Channel>) {
if (data == null) return;
for (const [k, v] of Object.entries(data)) {
(this as any)[k] = v;
}
}
} }

View File

@ -54,17 +54,19 @@ export default define(meta, paramDef, async (ps, user) => {
} }
} }
const keyPair = genRsaKeyPair(4096); const keyPair = await genRsaKeyPair(4096);
let channel!: Channel;
await db.transaction(async transactionalEntityManager => { await db.transaction(async transactionalEntityManager => {
const channel = await transactionalEntityManager.insert(Channel, { channel = await transactionalEntityManager.save(new Channel({
id: genId(), id: genId(),
createdAt: new Date(), createdAt: new Date(),
userId: user.id, userId: user.id,
name: ps.name, name: ps.name,
description: ps.description || null, description: ps.description || null,
bannerId: banner ? banner.id : null, bannerId: banner ? banner.id : null,
}).then(x => Channels.findOneByOrFail(x.identifiers[0])); }));
await transactionalEntityManager.insert(ChannelKeypair, { await transactionalEntityManager.insert(ChannelKeypair, {
publicKey: keyPair.publicKey, publicKey: keyPair.publicKey,

View File

@ -159,12 +159,10 @@ const menu = computed(() => [{
} }
}]); }]);
const { lists, antennas, followedChannels, featuredChannels } = toRefs({ const lists = ref([]);
lists: [], const antennas = ref([]);
antennas: [], const followedChannels = ref([]);
followedChannels: [], const featuredChannels = ref([]);
featuredChannels: [],
});
function getSidebarContent() { function getSidebarContent() {
os.api('users/lists/list').then(newLists => { os.api('users/lists/list').then(newLists => {

View File

@ -4,12 +4,14 @@
<div v-if="date" class="info"> <div v-if="date" class="info">
<MkInfo>{{ i18n.ts.showingPastTimeline }} <button class="_textButton clear" @click="timetravel()">{{ i18n.ts.clear }}</button></MkInfo> <MkInfo>{{ i18n.ts.showingPastTimeline }} <button class="_textButton clear" @click="timetravel()">{{ i18n.ts.clear }}</button></MkInfo>
</div> </div>
<div class="top"> <div class="body" class="{ channel: channelId }">
<XPostForm/> <div class="postform">
</div> <XPostForm/>
<div ref="body" class="tl"> </div>
<div v-if="queue > 0" class="new" :style="{ width: width + 'px', top: top + 'px' }"><button class="_buttonPrimary" @click="goTop()">{{ i18n.ts.newNoteRecived }}</button></div> <div ref="scroller" class="tl">
<XNotes ref="tl" class="tl" :pagination="pagination" @queue="queueUpdated"/> <div v-if="queue > 0" class="new" :style="{ width: width + 'px', top: top + 'px' }"><button class="_buttonPrimary" @click="goTop()">{{ i18n.ts.newNoteRecived }}</button></div>
<XNotes ref="tl" class="tl" :pagination="pagination" @queue="queueUpdated"/>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -28,10 +30,12 @@ import { defaultStore } from '@/store';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
type Props = { type Props = {
src: string; tlSrc: string;
channelId?: string;
}; };
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
src: 'home', tlSrc: 'home',
channelId: null,
}); });
const emit = defineEmits(['note']); const emit = defineEmits(['note']);
@ -51,7 +55,7 @@ const typers = ref([]);
const date = ref(null); const date = ref(null);
const tl = ref(); const tl = ref();
const body = ref(); const scroller = ref();
definePageMetadata(computed(() => ({ definePageMetadata(computed(() => ({
title: i18n.ts.timeline, title: i18n.ts.timeline,
@ -82,8 +86,7 @@ const connection2 = ref(null);
const endpoint = ref(null); const endpoint = ref(null);
watchEffect((onCleanup) => { watchEffect((onCleanup) => {
console.log(props.src, defaultStore.state.numberOfPageCache); if (props.tlSrc == 'home') {
if (props.src == 'home') {
endpoint.value = 'notes/timeline'; endpoint.value = 'notes/timeline';
connection.value = markRaw(stream.useChannel('homeTimeline')); connection.value = markRaw(stream.useChannel('homeTimeline'));
connection.value.on('note', prepend); connection.value.on('note', prepend);
@ -91,22 +94,23 @@ watchEffect((onCleanup) => {
connection2.value = markRaw(stream.useChannel('main')); connection2.value = markRaw(stream.useChannel('main'));
connection2.value.on('follow', onChangeFollowing); connection2.value.on('follow', onChangeFollowing);
connection2.value.on('unfollow', onChangeFollowing); connection2.value.on('unfollow', onChangeFollowing);
} else if (props.src == 'local') { } else if (props.tlSrc == 'local') {
endpoint.value = 'notes/local-timeline'; endpoint.value = 'notes/local-timeline';
connection.value = markRaw(stream.useChannel('localTimeline')); connection.value = markRaw(stream.useChannel('localTimeline'));
connection.value.on('note', prepend); connection.value.on('note', prepend);
} else if (props.src == 'social') { } else if (props.tlSrc == 'social') {
endpoint.value = 'notes/hybrid-timeline'; endpoint.value = 'notes/hybrid-timeline';
connection.value = markRaw(stream.useChannel('hybridTimeline')); connection.value = markRaw(stream.useChannel('hybridTimeline'));
connection.value.on('note', prepend); connection.value.on('note', prepend);
} else if (props.src == 'global') { } else if (props.tlSrc == 'global') {
endpoint.value = 'notes/global-timeline'; endpoint.value = 'notes/global-timeline';
connection.value = markRaw(stream.useChannel('globalTimeline')); connection.value = markRaw(stream.useChannel('globalTimeline'));
connection.value.on('note', prepend); connection.value.on('note', prepend);
} else if (props.tlSrc == 'channel') {
} }
onCleanup(() => { onCleanup(() => {
console.log('cleaning');
connection.value.dispose(); connection.value.dispose();
if (connection2.value) connection2.value.dispose(); if (connection2.value) connection2.value.dispose();
}); });
@ -123,20 +127,20 @@ const pagination = computed(() => ({
function focus() { function focus() {
body.value.focus(); scroller.value.focus();
}; };
function goTop() { function goTop() {
const container = getScrollContainer(body.value); const container = getScrollContainer(scroller.value);
container.scrollTop = 0; container.scrollTop = 0;
}; };
function queueUpdated(q) { function queueUpdated(q) {
if (body.value.offsetWidth !== 0) { if (scroller.value.offsetWidth !== 0) {
const rect = body.value.getBoundingClientRect(); const rect = scroller.value.getBoundingClientRect();
this.width = body.value.offsetWidth; this.width = scroller.value.offsetWidth;
top.value = rect.top; top.value = rect.top;
bottom.value = body.value.offsetHeight; bottom.value = scroller.value.offsetHeight;
} }
queue.value = q; queue.value = q;
}; };
@ -158,11 +162,11 @@ function timetravel(target?: Date) {
padding: 16px 16px 0 16px; padding: 16px 16px 0 16px;
} }
> .top { .postform {
padding: 16px 16px 0 16px; padding: 16px 16px 0 16px;
} }
> .bottom { .bottom {
padding: 0 16px 16px 16px; padding: 0 16px 16px 16px;
position: relative; position: relative;

View File

@ -7,99 +7,81 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { ref, reactive, computed } from 'vue';
import * as os from '@/os'; import * as os from '@/os';
import copyToClipboard from '@/scripts/copy-to-clipboard'; import copyToClipboard from '@/scripts/copy-to-clipboard';
import { i18n } from '@/i18n';
import { useRouter } from '@/router'; import { useRouter } from '@/router';
import { url } from '@/config'; import { url as baseUrl } from '@/config';
const router = useRouter(); const router = useRouter();
const history = reactive([]);
const path = ref(null);
const component = ref(null);
const props = ref({});
export default defineComponent({ const emit = defineEmits(['open', 'close']);
components: {
},
provide() { const url = computed(() => baseUrl + path.value)
return {
navHook: (path) => {
this.navigate(path);
}
};
},
data() { const pageInfo = null;
return {
path: null,
component: null,
props: {},
pageInfo: null,
history: [],
};
},
computed: { function navigate(path, record = true) {
url(): string { if (record && path.value) history.push(path.value);
return url + this.path; path.value = path;
const { component: newComponent, props: newProps } = router.resolve(path);
component.value = newComponent;
props.value = newProps;
emit('open');
}
function back() {
navigate(history.pop(), false);
}
function close() {
path.value = null;
component.value = null;
props.value = {};
emit('close');
}
function onContextmenu(e) {
os.contextMenu([{
type: 'label',
text: this.path,
}, {
icon: 'fas fa-expand-alt',
text: i18n.ts.showInPage,
action: () => {
router.push(path);
close();
} }
}, }, {
icon: 'fas fa-window-maximize',
methods: { text: i18n.ts.openInWindow,
navigate(path, record = true) { action: () => {
if (record && this.path) this.history.push(this.path); os.pageWindow(path);
this.path = path; close();
const { component, props } = resolve(path);
this.component = component;
this.props = props;
this.$emit('open');
},
back() {
this.navigate(this.history.pop(), false);
},
close() {
this.path = null;
this.component = null;
this.props = {};
this.$emit('close');
},
onContextmenu(e) {
os.contextMenu([{
type: 'label',
text: this.path,
}, {
icon: 'fas fa-expand-alt',
text: this.$ts.showInPage,
action: () => {
router.push(this.path);
this.close();
}
}, {
icon: 'fas fa-window-maximize',
text: this.$ts.openInWindow,
action: () => {
os.pageWindow(this.path);
this.close();
}
}, null, {
icon: 'fas fa-external-link-alt',
text: this.$ts.openInNewTab,
action: () => {
window.open(this.url, '_blank');
this.close();
}
}, {
icon: 'fas fa-link',
text: this.$ts.copyLink,
action: () => {
copyToClipboard(this.url);
}
}], e);
} }
} }, null, {
}); icon: 'fas fa-external-link-alt',
text: i18n.ts.openInNewTab,
action: () => {
window.open(url, '_blank');
close();
}
}, {
icon: 'fas fa-link',
text: i18n.ts.copyLink,
action: () => {
copyToClipboard(url);
}
}], e);
}
defineExpose({ navHook: navigate });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>