diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 96398db6a..678f20e8c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -564,6 +564,19 @@ overview: "概要" logs: "ログ" delayed: "遅延" database: "データベース" +channel: "チャンネル" +create: "作成" + +_channel: + create: "チャンネルを作成" + edit: "チャンネルを編集" + setBanner: "バナーを設定" + removeBanner: "バナーを削除" + featured: "トレンド" + owned: "管理中" + following: "フォロー中" + usersCount: "{n}人が参加中" + notesCount: "{n}投稿があります" _sidebar: full: "フル" @@ -660,6 +673,7 @@ _sfx: chat: "チャット" chatBg: "チャット(バックグラウンド)" antenna: "アンテナ受信" + channel: "チャンネル通知" _ago: unknown: "謎" @@ -740,6 +754,8 @@ _permissions: "write:page-likes": "ページのいいねを操作する" "read:user-groups": "ユーザーグループを見る" "write:user-groups": "ユーザーグループを操作する" + "read:channels": "チャンネルを見る" + "write:channels": "チャンネルを操作する" _auth: shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" @@ -822,6 +838,7 @@ _visibility: _postForm: replyPlaceholder: "このノートに返信..." quotePlaceholder: "このノートを引用..." + channelPlaceholder: "チャンネルに投稿..." _placeholders: a: "いまどうしてる?" b: "何かありましたか?" diff --git a/migration/1596548170836-channel.ts b/migration/1596548170836-channel.ts new file mode 100644 index 000000000..4e3ebb330 --- /dev/null +++ b/migration/1596548170836-channel.ts @@ -0,0 +1,58 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class channel1596548170836 implements MigrationInterface { + name = 'channel1596548170836' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "channel" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "lastNotedAt" TIMESTAMP WITH TIME ZONE, "userId" character varying(32) NOT NULL, "name" character varying(128) NOT NULL, "description" character varying(2048), "bannerId" character varying(32), "notesCount" integer NOT NULL DEFAULT 0, "usersCount" integer NOT NULL DEFAULT 0, CONSTRAINT "PK_590f33ee6ee7d76437acf362e39" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_71cb7b435b7c0d4843317e7e16" ON "channel" ("createdAt") `); + await queryRunner.query(`CREATE INDEX "IDX_29ef80c6f13bcea998447fce43" ON "channel" ("lastNotedAt") `); + await queryRunner.query(`CREATE INDEX "IDX_823bae55bd81b3be6e05cff438" ON "channel" ("userId") `); + await queryRunner.query(`CREATE INDEX "IDX_0f58c11241e649d2a638a8de94" ON "channel" ("notesCount") `); + await queryRunner.query(`CREATE INDEX "IDX_094b86cd36bb805d1aa1e8cc9a" ON "channel" ("usersCount") `); + await queryRunner.query(`CREATE TABLE "channel_following" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "followeeId" character varying(32) NOT NULL, "followerId" character varying(32) NOT NULL, CONSTRAINT "PK_8b104be7f7415113f2a02cd5bdd" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_11e71f2511589dcc8a4d3214f9" ON "channel_following" ("createdAt") `); + await queryRunner.query(`CREATE INDEX "IDX_0e43068c3f92cab197c3d3cd86" ON "channel_following" ("followeeId") `); + await queryRunner.query(`CREATE INDEX "IDX_6d8084ec9496e7334a4602707e" ON "channel_following" ("followerId") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_2e230dd45a10e671d781d99f3e" ON "channel_following" ("followerId", "followeeId") `); + await queryRunner.query(`CREATE TABLE "channel_note_pining" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "channelId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, CONSTRAINT "PK_44f7474496bcf2e4b741681146d" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_8125f950afd3093acb10d2db8a" ON "channel_note_pining" ("channelId") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_f36fed37d6d4cdcc68c803cd9c" ON "channel_note_pining" ("channelId", "noteId") `); + await queryRunner.query(`ALTER TABLE "note" ADD "channelId" character varying(32) DEFAULT null`); + await queryRunner.query(`CREATE INDEX "IDX_f22169eb10657bded6d875ac8f" ON "note" ("channelId") `); + await queryRunner.query(`ALTER TABLE "channel" ADD CONSTRAINT "FK_823bae55bd81b3be6e05cff4383" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "channel" ADD CONSTRAINT "FK_999da2bcc7efadbfe0e92d3bc19" FOREIGN KEY ("bannerId") REFERENCES "drive_file"("id") ON DELETE SET NULL ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "note" ADD CONSTRAINT "FK_f22169eb10657bded6d875ac8f9" FOREIGN KEY ("channelId") REFERENCES "channel"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "channel_following" ADD CONSTRAINT "FK_0e43068c3f92cab197c3d3cd86e" FOREIGN KEY ("followeeId") REFERENCES "channel"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "channel_following" ADD CONSTRAINT "FK_6d8084ec9496e7334a4602707e1" FOREIGN KEY ("followerId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "channel_note_pining" ADD CONSTRAINT "FK_8125f950afd3093acb10d2db8a8" FOREIGN KEY ("channelId") REFERENCES "channel"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "channel_note_pining" ADD CONSTRAINT "FK_10b19ef67d297ea9de325cd4502" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "channel_note_pining" DROP CONSTRAINT "FK_10b19ef67d297ea9de325cd4502"`); + await queryRunner.query(`ALTER TABLE "channel_note_pining" DROP CONSTRAINT "FK_8125f950afd3093acb10d2db8a8"`); + await queryRunner.query(`ALTER TABLE "channel_following" DROP CONSTRAINT "FK_6d8084ec9496e7334a4602707e1"`); + await queryRunner.query(`ALTER TABLE "channel_following" DROP CONSTRAINT "FK_0e43068c3f92cab197c3d3cd86e"`); + await queryRunner.query(`ALTER TABLE "note" DROP CONSTRAINT "FK_f22169eb10657bded6d875ac8f9"`); + await queryRunner.query(`ALTER TABLE "channel" DROP CONSTRAINT "FK_999da2bcc7efadbfe0e92d3bc19"`); + await queryRunner.query(`ALTER TABLE "channel" DROP CONSTRAINT "FK_823bae55bd81b3be6e05cff4383"`); + await queryRunner.query(`DROP INDEX "IDX_f22169eb10657bded6d875ac8f"`); + await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "channelId"`); + await queryRunner.query(`DROP INDEX "IDX_f36fed37d6d4cdcc68c803cd9c"`); + await queryRunner.query(`DROP INDEX "IDX_8125f950afd3093acb10d2db8a"`); + await queryRunner.query(`DROP TABLE "channel_note_pining"`); + await queryRunner.query(`DROP INDEX "IDX_2e230dd45a10e671d781d99f3e"`); + await queryRunner.query(`DROP INDEX "IDX_6d8084ec9496e7334a4602707e"`); + await queryRunner.query(`DROP INDEX "IDX_0e43068c3f92cab197c3d3cd86"`); + await queryRunner.query(`DROP INDEX "IDX_11e71f2511589dcc8a4d3214f9"`); + await queryRunner.query(`DROP TABLE "channel_following"`); + await queryRunner.query(`DROP INDEX "IDX_094b86cd36bb805d1aa1e8cc9a"`); + await queryRunner.query(`DROP INDEX "IDX_0f58c11241e649d2a638a8de94"`); + await queryRunner.query(`DROP INDEX "IDX_823bae55bd81b3be6e05cff438"`); + await queryRunner.query(`DROP INDEX "IDX_29ef80c6f13bcea998447fce43"`); + await queryRunner.query(`DROP INDEX "IDX_71cb7b435b7c0d4843317e7e16"`); + await queryRunner.query(`DROP TABLE "channel"`); + } + +} diff --git a/migration/1596786425167-channel2.ts b/migration/1596786425167-channel2.ts new file mode 100644 index 000000000..0233f7ab0 --- /dev/null +++ b/migration/1596786425167-channel2.ts @@ -0,0 +1,14 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class channel21596786425167 implements MigrationInterface { + name = 'channel21596786425167' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "channel_following" DROP COLUMN "readCursor"`); + } + +} diff --git a/migration/1597459042300-channel-unread.ts b/migration/1597459042300-channel-unread.ts new file mode 100644 index 000000000..a0f862114 --- /dev/null +++ b/migration/1597459042300-channel-unread.ts @@ -0,0 +1,27 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class channelUnread1597459042300 implements MigrationInterface { + name = 'channelUnread1597459042300' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`TRUNCATE TABLE "note_unread"`, undefined); + await queryRunner.query(`ALTER TABLE "channel_following" DROP COLUMN "readCursor"`); + await queryRunner.query(`ALTER TABLE "note_unread" ADD "isMentioned" boolean NOT NULL`); + await queryRunner.query(`ALTER TABLE "note_unread" ADD "noteChannelId" character varying(32)`); + await queryRunner.query(`CREATE INDEX "IDX_25b1dd384bec391b07b74b861c" ON "note_unread" ("isMentioned") `); + await queryRunner.query(`CREATE INDEX "IDX_89a29c9237b8c3b6b3cbb4cb30" ON "note_unread" ("isSpecified") `); + await queryRunner.query(`CREATE INDEX "IDX_29e8c1d579af54d4232939f994" ON "note_unread" ("noteUserId") `); + await queryRunner.query(`CREATE INDEX "IDX_6a57f051d82c6d4036c141e107" ON "note_unread" ("noteChannelId") `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_6a57f051d82c6d4036c141e107"`); + await queryRunner.query(`DROP INDEX "IDX_29e8c1d579af54d4232939f994"`); + await queryRunner.query(`DROP INDEX "IDX_89a29c9237b8c3b6b3cbb4cb30"`); + await queryRunner.query(`DROP INDEX "IDX_25b1dd384bec391b07b74b861c"`); + await queryRunner.query(`ALTER TABLE "note_unread" DROP COLUMN "noteChannelId"`); + await queryRunner.query(`ALTER TABLE "note_unread" DROP COLUMN "isMentioned"`); + await queryRunner.query(`ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`); + } + +} diff --git a/src/client/assets/sounds/noizenecio/kick_gaba2.mp3 b/src/client/assets/sounds/noizenecio/kick_gaba2.mp3 new file mode 100644 index 000000000..33c283762 Binary files /dev/null and b/src/client/assets/sounds/noizenecio/kick_gaba2.mp3 differ diff --git a/src/client/assets/sounds/syuilo/reverved.mp3 b/src/client/assets/sounds/syuilo/reverved.mp3 new file mode 100644 index 000000000..47588ef27 Binary files /dev/null and b/src/client/assets/sounds/syuilo/reverved.mp3 differ diff --git a/src/client/assets/sounds/syuilo/ryukyu.mp3 b/src/client/assets/sounds/syuilo/ryukyu.mp3 new file mode 100644 index 000000000..9e935e3f3 Binary files /dev/null and b/src/client/assets/sounds/syuilo/ryukyu.mp3 differ diff --git a/src/client/assets/sounds/syuilo/square-pico.mp3 b/src/client/assets/sounds/syuilo/square-pico.mp3 new file mode 100644 index 000000000..c4d8305ae Binary files /dev/null and b/src/client/assets/sounds/syuilo/square-pico.mp3 differ diff --git a/src/client/components/channel-follow-button.vue b/src/client/components/channel-follow-button.vue new file mode 100644 index 000000000..3b83865b5 --- /dev/null +++ b/src/client/components/channel-follow-button.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/src/client/components/channel-preview.vue b/src/client/components/channel-preview.vue new file mode 100644 index 000000000..bef475957 --- /dev/null +++ b/src/client/components/channel-preview.vue @@ -0,0 +1,144 @@ + + + + + diff --git a/src/client/components/note.vue b/src/client/components/note.vue index 99a088b3e..a731f9a36 100644 --- a/src/client/components/note.vue +++ b/src/client/components/note.vue @@ -57,6 +57,7 @@
+ {{ appearNote.channel.name }}