Skip to content

Commit

Permalink
Merge branch 'main' into fix/draft-whitespace
Browse files Browse the repository at this point in the history
  • Loading branch information
zcf0508 authored Jan 26, 2024
2 parents 0dab44d + 172883a commit c86f710
Show file tree
Hide file tree
Showing 149 changed files with 4,138 additions and 3,149 deletions.
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ dist
.netlify/
.eslintcache

public/shiki
public/emojis

*~
Expand Down
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ NUXT_CLOUDFLARE_ACCOUNT_ID=
NUXT_CLOUDFLARE_NAMESPACE_ID=
NUXT_CLOUDFLARE_API_TOKEN=

# 'cloudflare' | 'fs'
# 'cloudflare' | 'vercel' | 'fs'
NUXT_STORAGE_DRIVER=
NUXT_STORAGE_FS_BASE=

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: 18
cache: pnpm
Expand All @@ -31,7 +31,7 @@ jobs:
run: pnpm nuxi prepare

- name: 🧪 Test project
run: pnpm test tests/unit
run: pnpm test:ci

- name: 📝 Lint
run: pnpm lint
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@ jobs:
packages: write
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Docker meta
id: metal
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Build and push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 18

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/semantic-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ jobs:
name: Semantic Pull Request
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5.2.0
uses: amannn/action-semantic-pull-request@v5.4.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ node_modules
*.log
dist
.output
.pnpm-store
.nuxt
.env
.DS_Store
Expand All @@ -11,7 +12,6 @@ dist
.eslintcache
elk-translation-status.json

public/shiki
public/emojis

*~
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
20
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ One could put Elk behind popular reverse proxies with SSL Handling like Traefik,
1. adjust permissions of storage dir: ```sudo chown 911:911 ./elk-storage```
1. start container: ```docker-compose up -d```

Note: The provided Dockerfile creates a container which will eventually run Elk as non-root user and create a persistent named Docker volume upon first start (if that volume does not yet exist). This volume is always created with root permission. Failing to change the permissions of ```/elk/data``` inside this volume to UID:GID 911 (as specified for Elk in the Dockerfile) will prevent Elk from storing it's config for user accounts. You either have to fix the permission in the created named volume, or mount a directory with the correct permission to ```/elk/data``` into the container.
> [!NOTE]
> The provided Dockerfile creates a container which will eventually run Elk as non-root user and create a persistent named Docker volume upon first start (if that volume does not yet exist). This volume is always created with root permission. Failing to change the permissions of ```/elk/data``` inside this volume to UID:GID 911 (as specified for Elk in the Dockerfile) will prevent Elk from storing it's config for user accounts. You either have to fix the permission in the created named volume, or mount a directory with the correct permission to ```/elk/data``` into the container.

### Ecosystem
Expand Down Expand Up @@ -151,7 +152,7 @@ You can consult the [PWA documentation](https://docs.elk.zone/pwa) to learn more
- [UnoCSS](https://uno.antfu.me/) - The instant on-demand atomic CSS engine
- [Iconify](https://github.com/iconify/icon-sets#iconify-icon-sets-in-json-format) - Iconify icon sets in JSON format
- [Masto.js](https://neet.github.io/masto.js) - Mastodon API client in TypeScript
- [shiki](https://shiki.matsu.io/) - A beautiful Syntax Highlighter
- [shikiji](https://shikiji.netlify.app/) - A beautiful and powerful syntax highlighter
- [vite-plugin-pwa](https://github.com/vite-pwa/vite-plugin-pwa) - Prompt for update, Web Push Notifications and Web Share Target API

## 👨‍💻 Contributors
Expand Down
4 changes: 3 additions & 1 deletion app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ provideGlobalCommands()
const route = useRoute()
if (process.server && !route.path.startsWith('/settings')) {
const url = useRequestURL()
useHead({
meta: [
{ property: 'og:url', content: `https://elk.zone${route.path}` },
{ property: 'og:url', content: `${url.origin}${route.path}` },
],
})
}
Expand Down
4 changes: 2 additions & 2 deletions components/account/AccountFollowButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const { client } = $(useMasto())
async function unblock() {
relationship!.blocking = false
try {
const newRel = await client.v1.accounts.unblock(account.id)
const newRel = await client.v1.accounts.$select(account.id).unblock()
Object.assign(relationship!, newRel)
}
catch (err) {
Expand All @@ -32,7 +32,7 @@ async function unblock() {
async function unmute() {
relationship!.muting = false
try {
const newRel = await client.v1.accounts.unmute(account.id)
const newRel = await client.v1.accounts.$select(account.id).unmute()
Object.assign(relationship!, newRel)
}
catch (err) {
Expand Down
4 changes: 2 additions & 2 deletions components/account/AccountFollowRequestButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async function authorizeFollowRequest() {
relationship!.requestedBy = false
relationship!.followedBy = true
try {
const newRel = await client.v1.followRequests.authorize(account.id)
const newRel = await client.v1.followRequests.$select(account.id).authorize()
Object.assign(relationship!, newRel)
}
catch (err) {
Expand All @@ -25,7 +25,7 @@ async function authorizeFollowRequest() {
async function rejectFollowRequest() {
relationship!.requestedBy = false
try {
const newRel = await client.v1.followRequests.reject(account.id)
const newRel = await client.v1.followRequests.$select(account.id).reject()
Object.assign(relationship!, newRel)
}
catch (err) {
Expand Down
32 changes: 29 additions & 3 deletions components/account/AccountHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const namedFields = ref<mastodon.v1.AccountField[]>([])
const iconFields = ref<mastodon.v1.AccountField[]>([])
const isEditingPersonalNote = ref<boolean>(false)
const hasHeader = $computed(() => !account.header.endsWith('/original/missing.png'))
const isCopied = ref<boolean>(false)
function getFieldIconTitle(fieldName: string) {
return fieldName === 'Joined' ? t('account.joined') : fieldName
Expand Down Expand Up @@ -52,7 +53,7 @@ function previewAvatar() {
async function toggleNotifications() {
relationship!.notifying = !relationship?.notifying
try {
const newRel = await client.v1.accounts.follow(account.id, { notify: relationship?.notifying })
const newRel = await client.v1.accounts.$select(account.id).follow({ notify: relationship?.notifying })
Object.assign(relationship!, newRel)
}
catch {
Expand Down Expand Up @@ -96,7 +97,7 @@ async function editNote(event: Event) {
if (relationship.note?.trim() === newNote.trim())
return
const newNoteApiResult = await client.v1.accounts.createNote(account.id, { comment: newNote })
const newNoteApiResult = await client.v1.accounts.$select(account.id).note.create({ comment: newNote })
relationship.note = newNoteApiResult.note
personalNoteDraft.value = relationship.note ?? ''
}
Expand All @@ -105,6 +106,23 @@ const isSelf = $(useSelfAccount(() => account))
const isNotifiedOnPost = $computed(() => !!relationship?.notifying)
const personalNoteMaxLength = 2000
async function copyAccountName() {
try {
const shortHandle = getShortHandle(account)
const serverName = getServerName(account)
const accountName = `${shortHandle}@${serverName}`
await navigator.clipboard.writeText(accountName)
}
catch (err) {
console.error('Failed to copy account name:', err)
}
isCopied.value = true
setTimeout(() => {
isCopied.value = false
}, 2000)
}
</script>

<template>
Expand Down Expand Up @@ -175,7 +193,15 @@ const personalNoteMaxLength = 2000
<AccountLockIndicator v-if="account.locked" show-label />
<AccountBotIndicator v-if="account.bot" show-label />
</div>
<AccountHandle :account="account" overflow-unset line-clamp-unset />

<div flex items-center gap-1>
<AccountHandle :account="account" overflow-unset line-clamp-unset />
<CommonTooltip placement="bottom" :content="$t('account.copy_account_name')" no-auto-focus flex>
<button text-secondary-light text-sm :class="isCopied ? 'i-ri:check-fill text-green' : 'i-ri:file-copy-line'" @click="copyAccountName">
<span sr-only>{{ $t('account.copy_account_name') }}</span>
</button>
</CommonTooltip>
</div>
</div>
</div>
<label
Expand Down
4 changes: 3 additions & 1 deletion components/account/AccountLockIndicator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
defineProps<{
showLabel?: boolean
}>()
const { t } = useI18n()
</script>

<template>
Expand All @@ -15,7 +17,7 @@ defineProps<{
<div i-ri:lock-line />
</CommonTooltip>
<div v-if="showLabel">
Lock
{{ t('account.lock') }}
</div>
</div>
</template>
7 changes: 4 additions & 3 deletions components/account/AccountMoreButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ function shareAccount() {
async function toggleReblogs() {
if (!relationship!.showingReblogs && await openConfirmDialog({
title: t('confirm.show_reblogs.title', [account.acct]),
title: t('confirm.show_reblogs.title'),
description: t('confirm.show_reblogs.description', [account.acct]),
confirm: t('confirm.show_reblogs.confirm'),
cancel: t('confirm.show_reblogs.cancel'),
}) !== 'confirm')
return
const showingReblogs = !relationship?.showingReblogs
relationship = await client.v1.accounts.follow(account.id, { reblogs: showingReblogs })
relationship = await client.v1.accounts.$select(account.id).follow({ reblogs: showingReblogs })
}
async function addUserNote() {
Expand All @@ -44,7 +45,7 @@ async function removeUserNote() {
if (!relationship!.note || relationship!.note.length === 0)
return
const newNote = await client.v1.accounts.createNote(account.id, { comment: '' })
const newNote = await client.v1.accounts.$select(account.id).note.create({ comment: '' })
relationship!.note = newNote.note
emit('removeNote')
}
Expand Down
4 changes: 2 additions & 2 deletions components/account/AccountPaginator.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import type { Paginator, mastodon } from 'masto'
import type { mastodon } from 'masto'
const { paginator, account, context } = defineProps<{
paginator: Paginator<mastodon.v1.Account[], mastodon.DefaultPaginationParams>
paginator: mastodon.Paginator<mastodon.v1.Account[], mastodon.DefaultPaginationParams | undefined>
context?: 'following' | 'followers'
account?: mastodon.v1.Account
relationshipContext?: 'followedBy' | 'following'
Expand Down
10 changes: 4 additions & 6 deletions components/common/CommonPaginator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@
// @ts-expect-error missing types
import { DynamicScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import type { Paginator, WsEvents } from 'masto'
import type { mastodon } from 'masto'
import type { UnwrapRef } from 'vue'
const {
paginator,
stream,
keyProp = 'id',
virtualScroller = false,
eventType = 'update',
preprocess,
endMessage = true,
} = defineProps<{
paginator: Paginator<T[], O>
paginator: mastodon.Paginator<T[], O>
keyProp?: keyof T
virtualScroller?: boolean
stream?: Promise<WsEvents>
eventType?: 'notification' | 'update'
stream?: mastodon.streaming.Subscription
preprocess?: (items: (U | T)[]) => U[]
endMessage?: boolean | string
}>()
Expand Down Expand Up @@ -46,7 +44,7 @@ defineSlots<{
const { t } = useI18n()
const nuxtApp = useNuxtApp()
const { items, prevItems, update, state, endAnchor, error } = usePaginator(paginator, $$(stream), eventType, preprocess)
const { items, prevItems, update, state, endAnchor, error } = usePaginator(paginator, $$(stream), preprocess)
nuxtApp.hook('elk-logo:click', () => {
update()
Expand Down
2 changes: 1 addition & 1 deletion components/common/CommonTooltip.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { Popper as VTooltipType } from 'floating-vue/dist'
import type { Popper as VTooltipType } from 'floating-vue'
export interface Props extends Partial<typeof VTooltipType> {
content?: string
Expand Down
4 changes: 2 additions & 2 deletions components/conversation/ConversationPaginator.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import type { Paginator, mastodon } from 'masto'
import type { mastodon } from 'masto'
const { paginator } = defineProps<{
paginator: Paginator<mastodon.v1.Conversation[], mastodon.DefaultPaginationParams>
paginator: mastodon.Paginator<mastodon.v1.Conversation[], mastodon.DefaultPaginationParams>
}>()
function preprocess(items: mastodon.v1.Conversation[]): mastodon.v1.Conversation[] {
Expand Down
30 changes: 30 additions & 0 deletions components/emoji/Emoji.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<script setup lang="ts">
const { as, alt, dataEmojiId } = $defineProps<{
as: string
alt?: string
dataEmojiId?: string
}>()
let title = $ref<string | undefined>()
if (alt) {
if (alt.startsWith(':')) {
title = alt.replace(/:/g, '')
}
else {
import('node-emoji').then(({ find }) => {
title = find(alt)?.key.replace(/_/g, ' ')
})
}
}
// if it has a data-emoji-id, use that as the title instead
if (dataEmojiId)
title = dataEmojiId
</script>

<template>
<component :is="as" v-bind="$attrs" :alt="alt" :data-emoji-id="dataEmojiId" :title="title">
<slot />
</component>
</template>
Loading

0 comments on commit c86f710

Please sign in to comment.