mirror of
https://git.boykissers.com/pawkey/pawkey-sk.git
synced 2025-12-20 04:04:16 +00:00
feat: [frontend / backend] update git urls, update userid watermark, authenticate image proxy and url previews
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<!-- 💖 Thanks for taking the time to fill out this bug report!
|
<!-- 💖 Thanks for taking the time to fill out this bug report!
|
||||||
💁 Having trouble with deployment? [Ask the support chat.]()
|
💁 Having trouble with deployment? [Ask the support chat.]()
|
||||||
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://git.leafus.net/pawkey/pawkey/-/blob/stable/SECURITY.md)
|
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/SECURITY.md)
|
||||||
🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://git.leafus.net/pawkey/pawkey/-/blob/stable/CONTRIBUTING.md) -->
|
🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md) -->
|
||||||
|
|
||||||
# **What happened?**
|
# **What happened?**
|
||||||
<!-- Please give us a brief description of what happened. -->
|
<!-- Please give us a brief description of what happened. -->
|
||||||
@@ -30,6 +30,6 @@
|
|||||||
<!-- Please copy and paste any relevant log output. You can find your log by inspecting the page, and going to the "console" tab. This will be automatically formatted into code, so no need for backticks. -->
|
<!-- Please copy and paste any relevant log output. You can find your log by inspecting the page, and going to the "console" tab. This will be automatically formatted into code, so no need for backticks. -->
|
||||||
|
|
||||||
# **Contribution Guidelines**
|
# **Contribution Guidelines**
|
||||||
By submitting this issue, you agree to follow our [Contribution Guidelines](https://git.leafus.net/pawkey/pawkey/-/blob/stable/CONTRIBUTING.md)
|
By submitting this issue, you agree to follow our [Contribution Guidelines](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md)
|
||||||
- [ ] I agree to follow this project's Contribution Guidelines
|
- [ ] I agree to follow this project's Contribution Guidelines
|
||||||
- [ ] I have searched the issue tracker for similar issues, and this is not a duplicate.
|
- [ ] I have searched the issue tracker for similar issues, and this is not a duplicate.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- 💖 Thanks for taking the time to fill out this bug report!
|
<!-- 💖 Thanks for taking the time to fill out this bug report!
|
||||||
💁 Having trouble with deployment? [Ask the support chat.]()
|
💁 Having trouble with deployment? [Ask the support chat.]()
|
||||||
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://git.leafus.net/pawkey/pawkey/-/blob/stable/SECURITY.md)
|
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/SECURITY.md)
|
||||||
🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://git.leafus.net/pawkey/pawkey/-/blob/stable/CONTRIBUTING.md) -->
|
🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md) -->
|
||||||
|
|
||||||
# **What feature would you like implemented?**
|
# **What feature would you like implemented?**
|
||||||
<!-- Please give us a brief description of what you'd like. -->
|
<!-- Please give us a brief description of what you'd like. -->
|
||||||
@@ -16,6 +16,6 @@
|
|||||||
<!-- What instance of Pawkey are you using? -->
|
<!-- What instance of Pawkey are you using? -->
|
||||||
|
|
||||||
# **Contribution Guidelines**
|
# **Contribution Guidelines**
|
||||||
By submitting this issue, you agree to follow our [Contribution Guidelines](https://activitypub.software/TransFem-org/Pawkey/-/blob/develop/CONTRIBUTING.md)
|
By submitting this issue, you agree to follow our [Contribution Guidelines](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md)
|
||||||
- [ ] I agree to follow this project's Contribution Guidelines
|
- [ ] I agree to follow this project's Contribution Guidelines
|
||||||
- [ ] I have searched the issue tracker for similar requests, and this is not a duplicate.
|
- [ ] I have searched the issue tracker for similar requests, and this is not a duplicate.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
%{all_commits}
|
%{all_commits}
|
||||||
|
|
||||||
# **Contribution Guidelines**
|
# **Contribution Guidelines**
|
||||||
By submitting this merge request, you agree to follow our [Contribution Guidelines](https://git.leafus.net/pawkey/pawkey/-/blob/stable/CONTRIBUTING.md)
|
By submitting this merge request, you agree to follow our [Contribution Guidelines](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md)
|
||||||
- [ ] I agree to follow this project's Contribution Guidelines
|
- [ ] I agree to follow this project's Contribution Guidelines
|
||||||
- [ ] I have made sure to test this merge request
|
- [ ] I have made sure to test this merge request
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ An actual domain will be assigned so you can test the federation.
|
|||||||
- `x.y.z` is the new version you are trying to release.
|
- `x.y.z` is the new version you are trying to release.
|
||||||
3. Deploy and perform a simple QA check. Also verify that the tests passed.
|
3. Deploy and perform a simple QA check. Also verify that the tests passed.
|
||||||
4. Merge it. (Do not squash commit)
|
4. Merge it. (Do not squash commit)
|
||||||
5. Create a [release](https://git.leafus.net/pawkey/pawkey/-/releases)
|
5. Create a [release](https://git.pawlickers.org/pawkey/pawkey/releases)
|
||||||
- The target branch must be `stable`
|
- The target branch must be `stable`
|
||||||
- The tag name must be the version
|
- The tag name must be the version
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://pawkey.dev">
|
<a href="https://pawkey.dev">
|
||||||
<img src="https://git.leafus.net/pawkey/pawkey/-/raw/stable/packages/frontend/assets/pawkey.png" alt="Pawkey logo" width="300"/>
|
<img src="https://git.pawlickers.org/pawkey/pawkey/raw/branch/stable/packages/frontend/assets/pawkey.png" alt="Pawkey logo" width="300"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
**🌎 **[Pawkey](https://pawkey.dev)** is an open source, decentralized social media platform that's free forever! 🚀**
|
**🌎 **[Pawkey](https://pawkey.dev)** is an open source, decentralized social media platform that's free forever! 🚀**
|
||||||
|
|||||||
2
locales/index.d.ts
vendored
2
locales/index.d.ts
vendored
@@ -4888,7 +4888,7 @@ export interface Locale extends ILocale {
|
|||||||
*/
|
*/
|
||||||
"repositoryUrl": string;
|
"repositoryUrl": string;
|
||||||
/**
|
/**
|
||||||
* If there is a repository where the source code is publicly available, enter its URL. If you are using Pawkey as-is (without any changes to the source code), enter https://git.leafus.net/pawkey/pawkey.
|
* If there is a repository where the source code is publicly available, enter its URL. If you are using Pawkey as-is (without any changes to the source code), enter https://git.pawlickers.org/pawkey/pawkey.
|
||||||
*/
|
*/
|
||||||
"repositoryUrlDescription": string;
|
"repositoryUrlDescription": string;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"codename": "pawjob",
|
"codename": "pawjob",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.leafus.net/pawkey/pawkey.git"
|
"url": "https://git.pawlickers.org/pawkey/pawkey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.6.0",
|
"packageManager": "pnpm@9.6.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
export class AddSomeUrls1557761316509 {
|
export class AddSomeUrls1557761316509 {
|
||||||
async up(queryRunner) {
|
async up(queryRunner) {
|
||||||
await queryRunner.query(`ALTER TABLE "meta" ADD "ToSUrl" character varying(512)`);
|
await queryRunner.query(`ALTER TABLE "meta" ADD "ToSUrl" character varying(512)`);
|
||||||
await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) NOT NULL DEFAULT 'https://git.leafus.net/pawkey/pawkey'`);
|
await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) NOT NULL DEFAULT 'https://git.pawlickers.org/pawkey/pawkey'`);
|
||||||
await queryRunner.query(`ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) DEFAULT 'https://git.leafus.net/pawkey/pawkey/issues/new/choose'`);
|
await queryRunner.query(`ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) DEFAULT 'https://git.pawlickers.org/pawkey/pawkey/issues/new'`);
|
||||||
}
|
}
|
||||||
async down(queryRunner) {
|
async down(queryRunner) {
|
||||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "feedbackUrl"`);
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "feedbackUrl"`);
|
||||||
|
|||||||
22
packages/backend/migration/1763436210524-ChangeGITUrls.js
Normal file
22
packages/backend/migration/1763436210524-ChangeGITUrls.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: pawinput and Pawkey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class ChangeGITUrls1763436210524 {
|
||||||
|
name = 'ChangeGITUrls1763436210524'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET DEFAULT 'https://git.pawlickers.org/pawkey/pawkey'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "feedbackUrl" SET DEFAULT 'https://git.pawlickers.org/pawkey/pawkey/issues/new'`);
|
||||||
|
await queryRunner.query(`UPDATE "meta" SET "repositoryUrl"=DEFAULT WHERE "repositoryUrl" IN ('https://git.leafus.net/pawkey/pawkey')`);
|
||||||
|
await queryRunner.query(`UPDATE "meta" SET "feedbackUrl"=DEFAULT WHERE "feedbackUrl" IN ('https://git.leafus.net/pawkey/pawkey/-/issues/new')`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET DEFAULT 'https://git.leafus.net/pawkey/pawkey'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "feedbackUrl" SET DEFAULT 'https://git.leafus.net/pawkey/pawkey/-/issues/new'`);
|
||||||
|
await queryRunner.query(`UPDATE "meta" SET "repositoryUrl"=DEFAULT WHERE "repositoryUrl" IN ('https://git.pawlickers.org/pawkey/pawkey')`);
|
||||||
|
await queryRunner.query(`UPDATE "meta" SET "feedbackUrl"=DEFAULT WHERE "feedbackUrl" IN ('https://git.pawlickers.org/pawkey/pawkey/issues/new')`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -483,7 +483,7 @@ export function loadConfig(): Config {
|
|||||||
videoThumbnailGenerator: config.videoThumbnailGenerator ?
|
videoThumbnailGenerator: config.videoThumbnailGenerator ?
|
||||||
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
|
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
|
||||||
: null,
|
: null,
|
||||||
userAgent: `Misskey/${version} (${config.url})`,
|
userAgent: `Pawkey/${version} (${config.url})`,
|
||||||
frontendEntry: frontendManifest['src/_boot_.ts'],
|
frontendEntry: frontendManifest['src/_boot_.ts'],
|
||||||
frontendManifestExists: frontendManifestExists,
|
frontendManifestExists: frontendManifestExists,
|
||||||
frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'],
|
frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'],
|
||||||
|
|||||||
@@ -458,14 +458,14 @@ export class MiMeta {
|
|||||||
|
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 1024,
|
length: 1024,
|
||||||
default: 'https://git.leafus.net/pawkey/pawkey/',
|
default: 'https://git.pawlickers.org/pawkey/pawkey/',
|
||||||
nullable: false,
|
nullable: false,
|
||||||
})
|
})
|
||||||
public repositoryUrl: string | null;
|
public repositoryUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 1024,
|
length: 1024,
|
||||||
default: 'https://git.leafus.net/pawkey/pawkey/-/issues/new',
|
default: 'https://git.pawlickers.org/pawkey/pawkey/issues/new',
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public feedbackUrl: string | null;
|
public feedbackUrl: string | null;
|
||||||
|
|||||||
@@ -108,6 +108,43 @@ export class FileServerService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const body = request.method === 'GET'
|
||||||
|
? request.query
|
||||||
|
: request.body;
|
||||||
|
|
||||||
|
let cookieToken: string | undefined;
|
||||||
|
if (request.headers.cookie) {
|
||||||
|
const cookies = request.headers.cookie.split(';').reduce((acc, cookie) => {
|
||||||
|
const [key, value] = cookie.trim().split('=');
|
||||||
|
acc[key] = value;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, string>);
|
||||||
|
cookieToken = cookies.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = request.headers.authorization?.startsWith('Bearer ')
|
||||||
|
? request.headers.authorization.slice(7)
|
||||||
|
: (body as any)?.['i'] ?? cookieToken;
|
||||||
|
|
||||||
|
if (token != null && typeof token !== 'string') {
|
||||||
|
reply.code(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [user] = await this.authenticateService.authenticate(token);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
reply.code(401);
|
||||||
|
reply.send({
|
||||||
|
error: {
|
||||||
|
message: 'Credential required.',
|
||||||
|
code: 'CREDENTIAL_REQUIRED',
|
||||||
|
id: '1384574d-a912-4b81-8601-c7b1c4085df1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const keyUrl = new URL(url);
|
const keyUrl = new URL(url);
|
||||||
keyUrl.searchParams.forEach(k => keyUrl.searchParams.delete(k));
|
keyUrl.searchParams.forEach(k => keyUrl.searchParams.delete(k));
|
||||||
keyUrl.hash = '';
|
keyUrl.hash = '';
|
||||||
@@ -632,7 +669,7 @@ export class FileServerService {
|
|||||||
// https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 (case sensitive)
|
// https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 (case sensitive)
|
||||||
const token = request.headers.authorization?.startsWith('Bearer ')
|
const token = request.headers.authorization?.startsWith('Bearer ')
|
||||||
? request.headers.authorization.slice(7)
|
? request.headers.authorization.slice(7)
|
||||||
: body?.['i'];
|
: (body as any)?.['i'];
|
||||||
if (token != null && typeof token !== 'string') {
|
if (token != null && typeof token !== 'string') {
|
||||||
reply.code(400);
|
reply.code(400);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -95,12 +95,27 @@ export class StreamingApiServerService {
|
|||||||
? request.headers.authorization.slice(7)
|
? request.headers.authorization.slice(7)
|
||||||
: q.get('i');
|
: q.get('i');
|
||||||
|
|
||||||
|
// Require authentication for WebSocket connections
|
||||||
|
if (!token) {
|
||||||
|
socket.write([
|
||||||
|
'HTTP/1.1 401 Unauthorized',
|
||||||
|
'WWW-Authenticate: Bearer realm="Misskey"',
|
||||||
|
].join('\r\n') + '\r\n\r\n');
|
||||||
|
socket.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
[user, app] = await this.authenticateService.authenticate(token);
|
[user, app] = await this.authenticateService.authenticate(token);
|
||||||
|
|
||||||
if (app !== null && !app.permission.some(p => p === 'read:account')) {
|
if (app !== null && !app.permission.some(p => p === 'read:account')) {
|
||||||
throw new AuthenticationError('Your app does not have necessary permissions to use websocket API.');
|
throw new AuthenticationError('Your app does not have necessary permissions to use websocket API.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we have a valid user
|
||||||
|
if (!user) {
|
||||||
|
throw new AuthenticationError('Invalid token or user not found.');
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof AuthenticationError) {
|
if (e instanceof AuthenticationError) {
|
||||||
socket.write([
|
socket.write([
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) {
|
|||||||
|
|
||||||
externalDocs: {
|
externalDocs: {
|
||||||
description: 'Repository',
|
description: 'Repository',
|
||||||
url: 'https://git.leafus.net/pawkey/pawkey',
|
url: 'https://git.pawlickers.org/pawkey/pawkey',
|
||||||
},
|
},
|
||||||
|
|
||||||
servers: [{
|
servers: [{
|
||||||
@@ -97,7 +97,7 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) {
|
|||||||
description: desc,
|
description: desc,
|
||||||
externalDocs: {
|
externalDocs: {
|
||||||
description: 'Source code',
|
description: 'Source code',
|
||||||
url: `https://git.leafus.net/pawkey/pawkey/-/tree/stable/packages/backend/src/server/api/endpoints/${endpoint.name}.ts`,
|
url: `https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/packages/backend/src/server/api/endpoints/${endpoint.name}.ts`,
|
||||||
},
|
},
|
||||||
...(endpoint.meta.tags ? {
|
...(endpoint.meta.tags ? {
|
||||||
tags: [endpoint.meta.tags[0]],
|
tags: [endpoint.meta.tags[0]],
|
||||||
|
|||||||
@@ -169,8 +169,22 @@ export class UrlPreviewService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check rate limit
|
// Check authentication
|
||||||
const auth = await this.authenticate(request);
|
const auth = await this.authenticate(request);
|
||||||
|
const [user] = auth;
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
reply.code(401);
|
||||||
|
return reply.send({
|
||||||
|
error: {
|
||||||
|
message: 'Credential required.',
|
||||||
|
code: 'CREDENTIAL_REQUIRED',
|
||||||
|
id: '1384574d-a912-4b81-8601-c7b1c4085df1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check rate limit
|
||||||
if (!await this.checkRateLimit(auth, reply)) {
|
if (!await this.checkRateLimit(auth, reply)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -450,10 +464,21 @@ export class UrlPreviewService {
|
|||||||
private async authenticate(request: FastifyRequest<{ Querystring?: { i?: string | string[] }, Body?: { i?: string | string[] } }>): Promise<AuthArray> {
|
private async authenticate(request: FastifyRequest<{ Querystring?: { i?: string | string[] }, Body?: { i?: string | string[] } }>): Promise<AuthArray> {
|
||||||
const body = request.method === 'GET' ? request.query : request.body;
|
const body = request.method === 'GET' ? request.query : request.body;
|
||||||
|
|
||||||
|
// Parse token from cookie header if present
|
||||||
|
let cookieToken: string | undefined;
|
||||||
|
if (request.headers.cookie) {
|
||||||
|
const cookies = request.headers.cookie.split(';').reduce((acc, cookie) => {
|
||||||
|
const [key, value] = cookie.trim().split('=');
|
||||||
|
acc[key] = value;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, string>);
|
||||||
|
cookieToken = cookies.token;
|
||||||
|
}
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 (case sensitive)
|
// https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 (case sensitive)
|
||||||
const token = request.headers.authorization?.startsWith('Bearer ')
|
const token = request.headers.authorization?.startsWith('Bearer ')
|
||||||
? request.headers.authorization.slice(7)
|
? request.headers.authorization.slice(7)
|
||||||
: body?.['i'];
|
: body?.['i'] ?? cookieToken;
|
||||||
if (token != null && typeof token !== 'string') {
|
if (token != null && typeof token !== 'string') {
|
||||||
return [undefined, undefined, getIpHash(request.ip)];
|
return [undefined, undefined, getIpHash(request.ip)];
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 382 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 774 KiB |
@@ -16,6 +16,7 @@ import { prefer } from '@/preferences.js';
|
|||||||
import { store } from '@/store.js';
|
import { store } from '@/store.js';
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
import { signout } from '@/signout.js';
|
import { signout } from '@/signout.js';
|
||||||
|
import Cookies from 'js-cookie';
|
||||||
|
|
||||||
type AccountWithToken = Misskey.entities.MeDetailed & { token: string };
|
type AccountWithToken = Misskey.entities.MeDetailed & { token: string };
|
||||||
|
|
||||||
@@ -186,6 +187,8 @@ export async function login(token: AccountWithToken['token'], redirect?: string)
|
|||||||
token,
|
token,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
Cookies.set('token', token, { expires: 365 * 100 });
|
||||||
|
|
||||||
await addAccount(host, me, token);
|
await addAccount(host, me, token);
|
||||||
|
|
||||||
if (redirect) {
|
if (redirect) {
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ export async function mainBoot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
||||||
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://git.leafus.net/pawkey/pawkey') {
|
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://git.pawlickers.org/pawkey/pawkey') {
|
||||||
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<template #label>{{ i18n.ts.basicNotesBeforeCreateAccount }}</template>
|
<template #label>{{ i18n.ts.basicNotesBeforeCreateAccount }}</template>
|
||||||
<template #suffix><i v-if="agreeNote" class="ti ti-check" style="color: var(--MI_THEME-success)"></i></template>
|
<template #suffix><i v-if="agreeNote" class="ti ti-check" style="color: var(--MI_THEME-success)"></i></template>
|
||||||
|
|
||||||
<a href="https://git.leafus.net/pawkey/pawkey/-/blob/stable/IMPORTANT_NOTES.md" class="_link" target="_blank">{{ i18n.ts.basicNotesBeforeCreateAccount }} <i class="ti ti-external-link"></i></a>
|
<a href="https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/IMPORTANT_NOTES.md" class="_link" target="_blank">{{ i18n.ts.basicNotesBeforeCreateAccount }} <i class="ti ti-external-link"></i></a>
|
||||||
|
|
||||||
<MkSwitch :modelValue="agreeNote" style="margin-top: 16px;" data-cy-signup-rules-notes-agree @update:modelValue="updateAgreeNote">{{ i18n.ts.agree }}</MkSwitch>
|
<MkSwitch :modelValue="agreeNote" style="margin-top: 16px;" data-cy-signup-rules-notes-agree @update:modelValue="updateAgreeNote">{{ i18n.ts.agree }}</MkSwitch>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const modal = useTemplateRef('modal');
|
|||||||
|
|
||||||
const whatIsNew = () => {
|
const whatIsNew = () => {
|
||||||
modal.value?.close();
|
modal.value?.close();
|
||||||
window.open(`https://git.leafus.net/pawkey/pawkey/-/releases/${version}`, '_blank');
|
window.open(`https://git.pawlickers.org/pawkey/pawkey/releases${version}`, '_blank');
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { $i } from "@/i.js";
|
import { $i } from "@/i.js";
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||||
|
|
||||||
const generateRandomClass = () => {
|
const generateRandomClass = () => {
|
||||||
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
@@ -14,10 +14,27 @@ const generateRandomClass = () => {
|
|||||||
const gridClass = ref(generateRandomClass());
|
const gridClass = ref(generateRandomClass());
|
||||||
const itemClasses = ref<string[]>([]);
|
const itemClasses = ref<string[]>([]);
|
||||||
const recreationKey = ref(0);
|
const recreationKey = ref(0);
|
||||||
|
const gridItemCount = ref(600);
|
||||||
let regenerationInterval: ReturnType<typeof setInterval> | null = null;
|
let regenerationInterval: ReturnType<typeof setInterval> | null = null;
|
||||||
let styleElement: HTMLStyleElement | null = null;
|
let styleElement: HTMLStyleElement | null = null;
|
||||||
let allCreatedClasses: string[] = [];
|
let allCreatedClasses: string[] = [];
|
||||||
|
|
||||||
|
// Calculate grid items based on screen resolution
|
||||||
|
const calculateGridItemCount = () => {
|
||||||
|
const width = window.innerWidth;
|
||||||
|
const height = window.innerHeight;
|
||||||
|
|
||||||
|
// Grid cell size: 80px width + 10px gap, 16px height + 10px gap (more concise)
|
||||||
|
const itemWidth = 80 + 10;
|
||||||
|
const itemHeight = 16 + 10;
|
||||||
|
|
||||||
|
const columns = Math.ceil(width / itemWidth);
|
||||||
|
const rows = Math.ceil(height / itemHeight);
|
||||||
|
|
||||||
|
// Add some buffer (20%) to ensure coverage during animations/scrolling
|
||||||
|
return Math.ceil(columns * rows * 1.2);
|
||||||
|
};
|
||||||
|
|
||||||
const encodeTextToPath = (text: string) => {
|
const encodeTextToPath = (text: string) => {
|
||||||
const charPaths: { [key: string]: string } = {
|
const charPaths: { [key: string]: string } = {
|
||||||
a: "M2,8 L4,2 L6,2 L8,8 M3,6 L7,6",
|
a: "M2,8 L4,2 L6,2 L8,8 M3,6 L7,6",
|
||||||
@@ -77,7 +94,7 @@ const encodeTextToPath = (text: string) => {
|
|||||||
);
|
);
|
||||||
path += translatedPath + " ";
|
path += translatedPath + " ";
|
||||||
}
|
}
|
||||||
xOffset += 10;
|
xOffset += 7; // Reduced from 10 to 7 for tighter spacing
|
||||||
});
|
});
|
||||||
|
|
||||||
return path.trim();
|
return path.trim();
|
||||||
@@ -95,7 +112,9 @@ const regenerateWatermark = () => {
|
|||||||
cleanupOldElements();
|
cleanupOldElements();
|
||||||
|
|
||||||
gridClass.value = generateRandomClass();
|
gridClass.value = generateRandomClass();
|
||||||
itemClasses.value = generateItemClasses(600);
|
const count = calculateGridItemCount();
|
||||||
|
gridItemCount.value = count;
|
||||||
|
itemClasses.value = generateItemClasses(count);
|
||||||
recreationKey.value++;
|
recreationKey.value++;
|
||||||
|
|
||||||
allCreatedClasses.push(gridClass.value, ...itemClasses.value);
|
allCreatedClasses.push(gridClass.value, ...itemClasses.value);
|
||||||
@@ -140,13 +159,13 @@ const createStyleElement = () => {
|
|||||||
.${className} svg {
|
.${className} svg {
|
||||||
opacity: 0.02 !important;
|
opacity: 0.02 !important;
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
height: 12px !important;
|
height: 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.${className} svg path {
|
.${className} svg path {
|
||||||
stroke: var(--MI_THEME-fg) !important;
|
stroke: var(--MI_THEME-fg) !important;
|
||||||
fill: none !important;
|
fill: none !important;
|
||||||
stroke-width: 1 !important;
|
stroke-width: 0.8 !important;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
@@ -160,10 +179,10 @@ const createStyleElement = () => {
|
|||||||
width: 100vw !important;
|
width: 100vw !important;
|
||||||
height: 100vh !important;
|
height: 100vh !important;
|
||||||
display: grid !important;
|
display: grid !important;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)) !important;
|
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)) !important;
|
||||||
grid-template-rows: repeat(auto-fill, minmax(20px, 1fr)) !important;
|
grid-template-rows: repeat(auto-fill, minmax(16px, 1fr)) !important;
|
||||||
gap: 20px !important;
|
gap: 10px !important;
|
||||||
padding: 20px !important;
|
padding: 10px !important;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
z-index: 999999999 !important;
|
z-index: 999999999 !important;
|
||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
@@ -177,24 +196,51 @@ const createStyleElement = () => {
|
|||||||
|
|
||||||
const watermarkText = computed(() => $i?.id || "not signed in");
|
const watermarkText = computed(() => $i?.id || "not signed in");
|
||||||
const pathData = computed(() => encodeTextToPath(watermarkText.value));
|
const pathData = computed(() => encodeTextToPath(watermarkText.value));
|
||||||
const textWidth = computed(() => watermarkText.value.length * 10 + 10);
|
const textWidth = computed(() => watermarkText.value.length * 7 + 10); // Adjusted for tighter spacing
|
||||||
|
|
||||||
|
let resizeTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
const handleResize = () => {
|
||||||
|
if (resizeTimeout) clearTimeout(resizeTimeout);
|
||||||
|
|
||||||
|
// Debounce resize to avoid excessive recalculations
|
||||||
|
resizeTimeout = setTimeout(() => {
|
||||||
|
regenerateWatermark();
|
||||||
|
}, 250);
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
itemClasses.value = generateItemClasses(600);
|
const count = calculateGridItemCount();
|
||||||
|
gridItemCount.value = count;
|
||||||
|
itemClasses.value = generateItemClasses(count);
|
||||||
allCreatedClasses.push(gridClass.value, ...itemClasses.value);
|
allCreatedClasses.push(gridClass.value, ...itemClasses.value);
|
||||||
createStyleElement();
|
createStyleElement();
|
||||||
|
|
||||||
regenerationInterval = setInterval(() => {
|
regenerationInterval = setInterval(() => {
|
||||||
itemClasses.value = generateItemClasses(600);
|
const count = calculateGridItemCount();
|
||||||
|
gridItemCount.value = count;
|
||||||
|
itemClasses.value = generateItemClasses(count);
|
||||||
allCreatedClasses.push(gridClass.value, ...itemClasses.value);
|
allCreatedClasses.push(gridClass.value, ...itemClasses.value);
|
||||||
regenerateWatermark();
|
regenerateWatermark();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
|
window.addEventListener("resize", handleResize);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (regenerationInterval) clearInterval(regenerationInterval);
|
||||||
|
if (resizeTimeout) clearTimeout(resizeTimeout);
|
||||||
|
window.removeEventListener("resize", handleResize);
|
||||||
|
cleanupOldElements();
|
||||||
|
if (styleElement && styleElement.parentNode) {
|
||||||
|
styleElement.parentNode.removeChild(styleElement);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :key="`watermark-${recreationKey}`" :class="gridClass">
|
<div :key="`watermark-${recreationKey}`" :class="gridClass">
|
||||||
<div v-for="n in 600" :key="n" :class="itemClasses[n]">
|
<div v-for="n in gridItemCount" :key="n" :class="itemClasses[n]">
|
||||||
<svg :viewBox="`0 0 ${textWidth} 10`" xmlns="http://www.w3.org/2000/svg">
|
<svg :viewBox="`0 0 ${textWidth} 10`" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path :d="pathData" />
|
<path :d="pathData" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<button v-if="thereIsTreasure" class="_button treasure" @click="getTreasure"><img src="/fluent-emoji/1f3c6.png" class="treasureImg"></button>
|
<button v-if="thereIsTreasure" class="_button treasure" @click="getTreasure"><img src="/fluent-emoji/1f3c6.png" class="treasureImg"></button>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
{{ i18n.ts._aboutMisskey.about }}<br><a href="https://leafus.net/pawkey" target="_blank" class="_link">{{ i18n.ts.learnMore }}</a>
|
{{ i18n.ts._aboutMisskey.about }}<br><a href="https://pawkey.dev" target="_blank" class="_link">{{ i18n.ts.learnMore }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="$i != null" style="text-align: center;">
|
<div v-if="$i != null" style="text-align: center;">
|
||||||
<MkButton primary rounded inline @click="iLoveMisskey">I <Mfm text="$[jelly ❤]"/> #Pawkey</MkButton>
|
<MkButton primary rounded inline @click="iLoveMisskey">I <Mfm text="$[jelly ❤]"/> #Pawkey</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<FormSection v-if="instance.repositoryUrl !== 'https://git.leafus.net/pawkey/pawkey'">
|
<FormSection v-if="instance.repositoryUrl !== 'https://git.pawlickers.org/pawkey/pawkey'">
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<FormLink v-if="instance.repositoryUrl" :to="instance.repositoryUrl" external>
|
<FormLink v-if="instance.repositoryUrl" :to="instance.repositoryUrl" external>
|
||||||
<template #icon><i class="ti ti-code"></i></template>
|
<template #icon><i class="ti ti-code"></i></template>
|
||||||
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</FormSection>
|
</FormSection>
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<FormLink to="https://git.leafus.net/pawkey/pawkey" external>
|
<FormLink to="https://git.pawlickers.org/pawkey/pawkey" external>
|
||||||
<template #icon><i class="ph-code ph-bold ph-lg"></i></template>
|
<template #icon><i class="ph-code ph-bold ph-lg"></i></template>
|
||||||
{{ i18n.ts._aboutMisskey.source }} ({{ i18n.ts._aboutMisskey.original_pawkey }})
|
{{ i18n.ts._aboutMisskey.source }} ({{ i18n.ts._aboutMisskey.original_pawkey }})
|
||||||
<template #suffix>GitLab</template>
|
<template #suffix>GitLab</template>
|
||||||
@@ -128,81 +128,12 @@ const everyone = ref<Section[]>([
|
|||||||
heading: 'Pawkey Creators',
|
heading: 'Pawkey Creators',
|
||||||
people: fisher_yates([
|
people: fisher_yates([
|
||||||
{
|
{
|
||||||
handle: '@Leafus',
|
handle: '@pawinput',
|
||||||
avatar: 'https://git.leafus.net/uploads/-/system/user/avatar/2/avatar.png?width=192',
|
avatar: 'https://git.pawlickers.org/avatars/5e909e3e9e43b099242596d67debcd61264809b7765f160b01c8a376f23e47a5?size=512',
|
||||||
link: 'https://leafus.net',
|
link: 'https://pawlickers.org',
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
heading: 'Sharkey Contributors',
|
|
||||||
link: {
|
|
||||||
label: i18n.ts._aboutMisskey.allContributors,
|
|
||||||
url: 'https://activitypub.software/TransFem-org/Sharkey/-/graphs/develop',
|
|
||||||
},
|
|
||||||
people: fisher_yates([
|
|
||||||
{
|
|
||||||
handle: '@CenTdemeern1',
|
|
||||||
avatar: 'https://secure.gravatar.com/avatar/e97dd57d32caf703cea556ace6304617b7420f17f5b1aac4a1eea8e4234735bb?s=128&d=identicon',
|
|
||||||
link: 'https://activitypub.software/CenTdemeern1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@dakkar',
|
|
||||||
avatar: 'https://secure.gravatar.com/avatar/c71b315eed7c63ff94c42b1b3e8dbad1?s=128&d=identicon',
|
|
||||||
link: 'https://activitypub.software/dakkar',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@hazelnoot',
|
|
||||||
avatar: 'https://activitypub.software/uploads/-/system/user/avatar/5/avatar.png?width=128',
|
|
||||||
link: 'https://activitypub.software/fEmber',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@julia',
|
|
||||||
avatar: 'https://activitypub.software/uploads/-/system/user/avatar/41/avatar.png?width=128',
|
|
||||||
link: 'https://activitypub.software/julia',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@Luna',
|
|
||||||
avatar: 'https://secure.gravatar.com/avatar/4faf37df86a3d93a6c19ed6abf8588eade4efb837410dbbc53021b4fd12eaae7?s=128&d=identicon',
|
|
||||||
link: 'https://activitypub.software/luna',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@Marie',
|
|
||||||
avatar: 'https://activitypub.software/uploads/-/system/user/avatar/2/avatar.png?width=128',
|
|
||||||
link: 'https://activitypub.software/marie',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@supakaity',
|
|
||||||
avatar: 'https://activitypub.software/uploads/-/system/user/avatar/65/avatar.png?width=128',
|
|
||||||
link: 'https://activitypub.software/supakaity',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@tess',
|
|
||||||
avatar: 'https://activitypub.software/uploads/-/system/user/avatar/132/avatar.png?width=128',
|
|
||||||
link: 'https://activitypub.software/tess',
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
heading: 'Sharkey Testers',
|
|
||||||
people: [
|
|
||||||
{
|
|
||||||
handle: '@lucent',
|
|
||||||
avatar: 'https://antani.cyou/proxy/avatar.webp?url=https%3A%2F%2Fantani.cyou%2Ffiles%2Fa2944119-024c-4abd-86e5-64bf0d30b26f&avatar=1',
|
|
||||||
link: 'https://antani.cyou/@lucent',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@privateger',
|
|
||||||
avatar: 'https://mediaproxy.plasmatrap.com/?url=https%3A%2F%2Fplasmatrap.com%2Ffiles%2F2cf35a8f-6520-4d4c-9611-bf22ee983293&avatar=1',
|
|
||||||
link: 'https://plasmatrap.com/@privateger',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handle: '@phoenix_fairy',
|
|
||||||
avatar: 'https://thetransagenda.gay/proxy/avatar.webp?url=https%3A%2F%2Fs3.us-east-005.backblazeb2.com%2Ftranssharkey%2Fnull%2Fd93ac6dc-2020-4b5a-bce7-84b41e97a0ac.png&avatar=1',
|
|
||||||
link: 'https://thetransagenda.gay/@phoenix_fairy',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
heading: i18n.ts._aboutMisskey.misskeyContributors,
|
heading: i18n.ts._aboutMisskey.misskeyContributors,
|
||||||
people: [
|
people: [
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ clickToOpen: "Click to open notes"
|
|||||||
showBots: "Show bots in timeline"
|
showBots: "Show bots in timeline"
|
||||||
showRenotes: "Show boosts"
|
showRenotes: "Show boosts"
|
||||||
sourceCodeIsNotYetProvided: "The source code is not yet available. Please contact your administrator to fix this problem."
|
sourceCodeIsNotYetProvided: "The source code is not yet available. Please contact your administrator to fix this problem."
|
||||||
repositoryUrlDescription: "If there is a repository where the source code is publicly available, enter its URL. If you are using Pawkey as-is (without any changes to the source code), enter https://git.leafus.net/pawkey/pawkey."
|
repositoryUrlDescription: "If there is a repository where the source code is publicly available, enter its URL. If you are using Pawkey as-is (without any changes to the source code), enter https://git.pawlickers.org/pawkey/pawkey."
|
||||||
donation: "Donate"
|
donation: "Donate"
|
||||||
donationUrl: "Donation URL"
|
donationUrl: "Donation URL"
|
||||||
showBelowAvatar: "Show Below Avatar"
|
showBelowAvatar: "Show Below Avatar"
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ clickToOpen: "クリックしてノートを開く"
|
|||||||
showBots: "ボットをタイムラインに表示"
|
showBots: "ボットをタイムラインに表示"
|
||||||
showRenotes: "ブーストを表示"
|
showRenotes: "ブーストを表示"
|
||||||
sourceCodeIsNotYetProvided: "ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。"
|
sourceCodeIsNotYetProvided: "ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。"
|
||||||
repositoryUrlDescription: "ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Pawkeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://git.leafus.net/pawkey/pawkey と記入します。"
|
repositoryUrlDescription: "ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Pawkeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://git.pawlickers.org/pawkey/pawkey と記入します。"
|
||||||
donation: "寄付する"
|
donation: "寄付する"
|
||||||
donationUrl: "寄付URL"
|
donationUrl: "寄付URL"
|
||||||
showBelowAvatar: "アイコンの後ろに表示"
|
showBelowAvatar: "アイコンの後ろに表示"
|
||||||
|
|||||||
Reference in New Issue
Block a user