commit
3c986072bc
10
.eslintrc.js
10
.eslintrc.js
|
@ -34,10 +34,8 @@ module.exports = {
|
||||||
varsIgnorePattern: '^log$'
|
varsIgnorePattern: '^log$'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// TODO: Remove any usage and enable
|
'@typescript-eslint/no-explicit-any': 'warn',
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-non-null-assertion': 'warn',
|
||||||
// TODO: Fix errors and enable this rule
|
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
||||||
|
|
||||||
// solid-js fix
|
// solid-js fix
|
||||||
'import/no-unresolved': [2, { ignore: ['solid-js/'] }]
|
'import/no-unresolved': [2, { ignore: ['solid-js/'] }]
|
||||||
|
@ -58,8 +56,8 @@ module.exports = {
|
||||||
// FIXME
|
// FIXME
|
||||||
'solid/reactivity': 'off',
|
'solid/reactivity': 'off',
|
||||||
|
|
||||||
// TODO: Should be enabled
|
// Should be enabled
|
||||||
'promise/catch-or-return': 'off',
|
// 'promise/catch-or-return': 'off',
|
||||||
|
|
||||||
'solid/no-innerhtml': 'off',
|
'solid/no-innerhtml': 'off',
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { markdownOptions as markdown } from './mdx.config'
|
||||||
import type { CSSOptions } from 'vite'
|
import type { CSSOptions } from 'vite'
|
||||||
import defaultGenerateScopedName from 'postcss-modules/build/generateScopedName'
|
import defaultGenerateScopedName from 'postcss-modules/build/generateScopedName'
|
||||||
import { isDev } from './src/utils/config'
|
import { isDev } from './src/utils/config'
|
||||||
|
import { fileURLToPath, URL } from 'url'
|
||||||
|
|
||||||
const PATH_PREFIX = '/src/'
|
const PATH_PREFIX = '/src/'
|
||||||
|
|
||||||
|
@ -62,7 +63,8 @@ const astroConfig: AstroUserConfig = {
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': './src'
|
'./runtimeConfig': './runtimeConfig.browser',
|
||||||
|
'@': fileURLToPath(new URL('src', import.meta.url))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
css
|
css
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
import type { AstroUserConfig } from 'astro'
|
import type { AstroUserConfig } from 'astro'
|
||||||
|
import type { RehypePlugin } from '@astrojs/markdown-remark'
|
||||||
import { selectAll } from 'hast-util-select'
|
import { selectAll } from 'hast-util-select'
|
||||||
|
import rehypeToc from '@jsdevtools/rehype-toc'
|
||||||
|
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
||||||
|
import rehypeSlug from 'rehype-slug'
|
||||||
|
import remarkCodeTitles from 'remark-code-titles'
|
||||||
|
|
||||||
const write =
|
const write =
|
||||||
(cl) =>
|
(cl) =>
|
||||||
({ properties }) => {
|
({ properties }) => {
|
||||||
properties.className = properties.className ? properties.className + ' ' + cl : cl
|
properties.className = properties.className ? properties.className + ' ' + cl : cl
|
||||||
}
|
}
|
||||||
|
|
||||||
const adder = ([selector, className]) => {
|
const adder = ([selector, className]) => {
|
||||||
const writer = write(className)
|
const writer = write(className)
|
||||||
return (node) => selectAll(selector, node).forEach((el) => writer(el as any))
|
return (node) => selectAll(selector, node).forEach((el) => writer(el as any))
|
||||||
}
|
}
|
||||||
|
|
||||||
const addClasses = (additions) => {
|
const addClasses = (additions) => {
|
||||||
const adders = Object.entries(additions).map((entry) => adder(entry))
|
const adders = Object.entries(additions).map((entry) => adder(entry))
|
||||||
return (node) => adders.forEach((a) => a(node))
|
return (node) => adders.forEach((a) => a(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const markdownOptions: AstroUserConfig['markdown'] = {
|
export const markdownOptions: AstroUserConfig['markdown'] = {
|
||||||
// remarkPlugins: ['remark-code-titles'],
|
remarkPlugins: [remarkCodeTitles],
|
||||||
rehypePlugins: [
|
rehypePlugins: [
|
||||||
// 'rehype-slug',
|
rehypeSlug,
|
||||||
// ['rehype-autolink-headings', { behavior: 'prepend' }],
|
[rehypeToc as RehypePlugin<any[]>, { headings: ['h1', 'h2', 'h3'] }],
|
||||||
// ['rehype-toc', { headings: ['h2', 'h3'] }],
|
[rehypeAutolinkHeadings, { behavior: 'prepend' }],
|
||||||
[addClasses, { 'h1,h2,h3': 'title' }]
|
[addClasses, { 'h1,h2,h3': 'title' }]
|
||||||
]
|
],
|
||||||
|
extendDefaultPlugins: true
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,11 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.178.0",
|
"@aws-sdk/client-s3": "^3.178.0",
|
||||||
"@nanostores/i18n": "^0.7.0",
|
"@jsdevtools/rehype-toc": "^3.0.2",
|
||||||
"@nanostores/persistent": "^0.7.0",
|
"@nanostores/persistent": "^0.7.0",
|
||||||
"@nanostores/router": "^0.7.0",
|
"@nanostores/router": "^0.7.0",
|
||||||
"@nanostores/solid": "^0.3.0",
|
"@nanostores/solid": "^0.3.0",
|
||||||
"@solid-primitives/memo": "^1.0.2",
|
"@solid-primitives/memo": "^1.0.2",
|
||||||
"axios": "^0.27.2",
|
|
||||||
"google-translate-api-x": "^10.4.1",
|
|
||||||
"loglevel": "^1.8.0",
|
"loglevel": "^1.8.0",
|
||||||
"loglevel-plugin-prefix": "^0.8.4",
|
"loglevel-plugin-prefix": "^0.8.4",
|
||||||
"mailgun.js": "^8.0.1",
|
"mailgun.js": "^8.0.1",
|
||||||
|
@ -43,11 +41,10 @@
|
||||||
"postcss-modules": "^5.0.0",
|
"postcss-modules": "^5.0.0",
|
||||||
"rehype-autolink-headings": "^6.1.1",
|
"rehype-autolink-headings": "^6.1.1",
|
||||||
"rehype-slug": "^5.0.1",
|
"rehype-slug": "^5.0.1",
|
||||||
"rehype-toc": "^3.0.2",
|
|
||||||
"remark-code-titles": "^0.1.2"
|
"remark-code-titles": "^0.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/markdown-remark": "^1.1.2",
|
"@astrojs/markdown-remark": "1.1.2",
|
||||||
"@astrojs/mdx": "^0.11.1",
|
"@astrojs/mdx": "^0.11.1",
|
||||||
"@astrojs/node": "^1.0.1",
|
"@astrojs/node": "^1.0.1",
|
||||||
"@astrojs/partytown": "^1.0.0",
|
"@astrojs/partytown": "^1.0.0",
|
||||||
|
@ -59,6 +56,7 @@
|
||||||
"@graphql-codegen/typescript-operations": "^2.5.3",
|
"@graphql-codegen/typescript-operations": "^2.5.3",
|
||||||
"@graphql-codegen/typescript-urql": "^3.7.0",
|
"@graphql-codegen/typescript-urql": "^3.7.0",
|
||||||
"@graphql-codegen/urql-introspection": "^2.2.1",
|
"@graphql-codegen/urql-introspection": "^2.2.1",
|
||||||
|
"@graphql-tools/url-loader": "^7.16.4",
|
||||||
"@graphql-typed-document-node/core": "^3.1.1",
|
"@graphql-typed-document-node/core": "^3.1.1",
|
||||||
"@popperjs/core": "^2.11.6",
|
"@popperjs/core": "^2.11.6",
|
||||||
"@solid-devtools/debugger": "^0.9.1",
|
"@solid-devtools/debugger": "^0.9.1",
|
||||||
|
|
|
@ -24,7 +24,9 @@ export default (props: {
|
||||||
if (b?.toString().startsWith('<')) {
|
if (b?.toString().startsWith('<')) {
|
||||||
setBody(b)
|
setBody(b)
|
||||||
} else {
|
} else {
|
||||||
renderMarkdown(b, markdownOptions).then(({ code }) => setBody(code))
|
renderMarkdown(b, markdownOptions)
|
||||||
|
.then(({ code }) => setBody(code))
|
||||||
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const remove = () => {
|
const remove = () => {
|
||||||
|
|
|
@ -50,7 +50,9 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
if (props.article.body.startsWith('<')) {
|
if (props.article.body.startsWith('<')) {
|
||||||
setBody(props.article.body)
|
setBody(props.article.body)
|
||||||
} else {
|
} else {
|
||||||
renderMarkdown(props.article.body, markdownOptions).then(({ code }) => setBody(code))
|
renderMarkdown(props.article.body, markdownOptions)
|
||||||
|
.then(({ code }) => setBody(code))
|
||||||
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,13 @@ import type { Store } from 'solid-js/store'
|
||||||
import type { XmlFragment } from 'yjs'
|
import type { XmlFragment } from 'yjs'
|
||||||
import type { WebrtcProvider } from 'y-webrtc'
|
import type { WebrtcProvider } from 'y-webrtc'
|
||||||
import type { ProseMirrorExtension, ProseMirrorState } from './state'
|
import type { ProseMirrorExtension, ProseMirrorState } from './state'
|
||||||
|
import type { Reaction } from '../../../graphql/types.gen'
|
||||||
|
|
||||||
export const isMac = true
|
export const isMac = true
|
||||||
|
|
||||||
export const mod = isMac ? 'Cmd' : 'Ctrl'
|
export const mod = isMac ? 'Cmd' : 'Ctrl'
|
||||||
export const alt = isMac ? 'Cmd' : 'Alt'
|
export const alt = isMac ? 'Cmd' : 'Alt'
|
||||||
|
|
||||||
export const WEB_URL =
|
|
||||||
//'http://localhost:3000'
|
|
||||||
'https://discoursio-editor-app.vercel.app'
|
|
||||||
|
|
||||||
export interface Args {
|
export interface Args {
|
||||||
cwd?: string
|
cwd?: string
|
||||||
file?: string
|
file?: string
|
||||||
|
|
|
@ -3,10 +3,7 @@ import { v4 as uuidv4 } from 'uuid'
|
||||||
import type { EditorState } from 'prosemirror-state'
|
import type { EditorState } from 'prosemirror-state'
|
||||||
import { undo, redo } from 'prosemirror-history'
|
import { undo, redo } from 'prosemirror-history'
|
||||||
import { selectAll, deleteSelection } from 'prosemirror-commands'
|
import { selectAll, deleteSelection } from 'prosemirror-commands'
|
||||||
import * as Y from 'yjs'
|
|
||||||
import { undo as yUndo, redo as yRedo } from 'y-prosemirror'
|
import { undo as yUndo, redo as yRedo } from 'y-prosemirror'
|
||||||
import { WebrtcProvider } from 'y-webrtc'
|
|
||||||
import { uniqueNamesGenerator, adjectives, animals } from 'unique-names-generator'
|
|
||||||
import { debounce } from 'ts-debounce'
|
import { debounce } from 'ts-debounce'
|
||||||
// import * as remote from '../prosemirror/remote'
|
// import * as remote from '../prosemirror/remote'
|
||||||
import { createSchema, createExtensions, createEmptyText } from '../prosemirror/setup'
|
import { createSchema, createExtensions, createEmptyText } from '../prosemirror/setup'
|
||||||
|
@ -14,8 +11,8 @@ import { State, File, Config, ServiceError, newState } from '.'
|
||||||
// import { isTauri, mod } from '../env'
|
// import { isTauri, mod } from '../env'
|
||||||
import { serialize, createMarkdownParser } from '../prosemirror/markdown'
|
import { serialize, createMarkdownParser } from '../prosemirror/markdown'
|
||||||
import { isEmpty, isInitialized } from '../prosemirror/state'
|
import { isEmpty, isInitialized } from '../prosemirror/state'
|
||||||
import { Awareness } from 'y-protocols/awareness'
|
|
||||||
import { isServer } from 'solid-js/web'
|
import { isServer } from 'solid-js/web'
|
||||||
|
import { roomConnect } from '../../../utils/p2p'
|
||||||
|
|
||||||
const mod = 'Ctrl'
|
const mod = 'Ctrl'
|
||||||
const isTauri = false
|
const isTauri = false
|
||||||
|
@ -444,35 +441,8 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
|
||||||
const doStartCollab = (state: State): State => {
|
const doStartCollab = (state: State): State => {
|
||||||
const backup = state.args?.room && state.collab?.room !== state.args.room
|
const backup = state.args?.room && state.collab?.room !== state.args.room
|
||||||
const room = state.args?.room ?? uuidv4()
|
const room = state.args?.room ?? uuidv4()
|
||||||
|
const username = '' // FIXME: use authenticated user name
|
||||||
window.history.replaceState(null, '', `/${room}`)
|
const [type, provider] = roomConnect(room, username)
|
||||||
|
|
||||||
const ydoc = new Y.Doc()
|
|
||||||
const type = ydoc.getXmlFragment('prosemirror')
|
|
||||||
const webrtcOptions = {
|
|
||||||
awareness: new Awareness(ydoc),
|
|
||||||
filterBcConns: true,
|
|
||||||
maxConns: 33,
|
|
||||||
signaling: [
|
|
||||||
// 'wss://signaling.discours.io',
|
|
||||||
// 'wss://stun.l.google.com:19302',
|
|
||||||
'wss://y-webrtc-signaling-eu.herokuapp.com',
|
|
||||||
'wss://signaling.yjs.dev'
|
|
||||||
],
|
|
||||||
peerOpts: {},
|
|
||||||
password: ''
|
|
||||||
}
|
|
||||||
const provider = new WebrtcProvider(room, ydoc, webrtcOptions)
|
|
||||||
const username = uniqueNamesGenerator({
|
|
||||||
dictionaries: [adjectives, animals],
|
|
||||||
style: 'capital',
|
|
||||||
separator: ' ',
|
|
||||||
length: 2
|
|
||||||
})
|
|
||||||
|
|
||||||
provider.awareness.setLocalStateField('user', {
|
|
||||||
name: username
|
|
||||||
})
|
|
||||||
|
|
||||||
const extensions = createExtensions({
|
const extensions = createExtensions({
|
||||||
config: state.config,
|
config: state.config,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { createEffect, createSignal, Show, Suspense } from 'solid-js'
|
import { createEffect, createSignal, Show, Suspense } from 'solid-js'
|
||||||
import { FullArticle } from '../Article/FullArticle'
|
import { FullArticle } from '../Article/FullArticle'
|
||||||
import { t } from '../../utils/intl'
|
import { t } from '../../utils/intl'
|
||||||
|
|
||||||
import type { Shout } from '../../graphql/types.gen'
|
import type { Shout } from '../../graphql/types.gen'
|
||||||
import { loadArticleReactions, useReactionsStore } from '../../stores/zine/reactions'
|
import { loadArticleReactions, useReactionsStore } from '../../stores/zine/reactions'
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { gql } from '@urql/core'
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
export default gql`
|
export default gql`
|
||||||
mutation RegisterMutation($email: String!, $password: String!) {
|
mutation RegisterMutation($email: String!, $password: String, $username: String) {
|
||||||
registerUser(email: $email, password: $password) {
|
registerUser(email: $email, password: $password, username: $username) {
|
||||||
error
|
error
|
||||||
token
|
token
|
||||||
user {
|
user {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { devtoolsExchange } from '@urql/devtools'
|
||||||
import { isDev } from '../utils/config'
|
import { isDev } from '../utils/config'
|
||||||
|
|
||||||
export const baseUrl = 'https://newapi.discours.io'
|
export const baseUrl = 'https://newapi.discours.io'
|
||||||
//export const baseUrl = 'http://localhost:8000'
|
// export const baseUrl = 'http://localhost:8000'
|
||||||
|
|
||||||
const exchanges: Exchange[] = [dedupExchange, fetchExchange]
|
const exchanges: Exchange[] = [dedupExchange, fetchExchange]
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { gql } from '@urql/core'
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
export default gql`
|
export default gql`
|
||||||
query AuthorssAllQuery {
|
query AuthorsAllQuery {
|
||||||
authorsAll {
|
authorsAll {
|
||||||
_id: slug
|
_id: slug
|
||||||
slug
|
slug
|
||||||
|
|
23
src/graphql/query/my-chats.ts
Normal file
23
src/graphql/query/my-chats.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
|
export default gql`
|
||||||
|
query GetChatsQuery {
|
||||||
|
myChats {
|
||||||
|
messages {
|
||||||
|
chatId
|
||||||
|
id
|
||||||
|
author
|
||||||
|
body
|
||||||
|
replyTo
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
users {
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
pic
|
||||||
|
}
|
||||||
|
title
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
|
@ -32,9 +32,22 @@ export type Author = {
|
||||||
|
|
||||||
export type Chat = {
|
export type Chat = {
|
||||||
createdAt: Scalars['DateTime']
|
createdAt: Scalars['DateTime']
|
||||||
|
createdBy: User
|
||||||
description?: Maybe<Scalars['String']>
|
description?: Maybe<Scalars['String']>
|
||||||
id: Scalars['Int']
|
id: Scalars['Int']
|
||||||
|
messages?: Maybe<Array<Maybe<Message>>>
|
||||||
|
title?: Maybe<Scalars['String']>
|
||||||
updatedAt: Scalars['DateTime']
|
updatedAt: Scalars['DateTime']
|
||||||
|
users: Array<Maybe<User>>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ChatResult = {
|
||||||
|
createdAt: Scalars['DateTime']
|
||||||
|
createdBy?: Maybe<User>
|
||||||
|
error?: Maybe<Scalars['String']>
|
||||||
|
members: Array<Maybe<User>>
|
||||||
|
messages?: Maybe<Array<Maybe<Message>>>
|
||||||
|
title?: Maybe<Scalars['String']>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ChatUpdatedResult = {
|
export type ChatUpdatedResult = {
|
||||||
|
@ -140,10 +153,11 @@ export type Mutation = {
|
||||||
follow: Result
|
follow: Result
|
||||||
incrementView: Result
|
incrementView: Result
|
||||||
inviteAuthor: Result
|
inviteAuthor: Result
|
||||||
|
inviteChat: Result
|
||||||
markAsRead: Result
|
markAsRead: Result
|
||||||
rateUser: Result
|
rateUser: Result
|
||||||
refreshSession: AuthResult
|
refreshSession: AuthResult
|
||||||
registerUser: AuthResult
|
registerUser: User
|
||||||
removeAuthor: Result
|
removeAuthor: Result
|
||||||
sendLink: Result
|
sendLink: Result
|
||||||
unfollow: Result
|
unfollow: Result
|
||||||
|
@ -229,6 +243,11 @@ export type MutationInviteAuthorArgs = {
|
||||||
shout: Scalars['String']
|
shout: Scalars['String']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MutationInviteChatArgs = {
|
||||||
|
chatId: Scalars['String']
|
||||||
|
userslug: Scalars['String']
|
||||||
|
}
|
||||||
|
|
||||||
export type MutationMarkAsReadArgs = {
|
export type MutationMarkAsReadArgs = {
|
||||||
chatId: Scalars['String']
|
chatId: Scalars['String']
|
||||||
ids: Array<InputMaybe<Scalars['Int']>>
|
ids: Array<InputMaybe<Scalars['Int']>>
|
||||||
|
@ -242,6 +261,7 @@ export type MutationRateUserArgs = {
|
||||||
export type MutationRegisterUserArgs = {
|
export type MutationRegisterUserArgs = {
|
||||||
email: Scalars['String']
|
email: Scalars['String']
|
||||||
password?: InputMaybe<Scalars['String']>
|
password?: InputMaybe<Scalars['String']>
|
||||||
|
username?: InputMaybe<Scalars['String']>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MutationRemoveAuthorArgs = {
|
export type MutationRemoveAuthorArgs = {
|
||||||
|
@ -314,16 +334,17 @@ export type ProfileInput = {
|
||||||
export type Query = {
|
export type Query = {
|
||||||
authorsAll: Array<Maybe<User>>
|
authorsAll: Array<Maybe<User>>
|
||||||
collectionsAll: Array<Maybe<Collection>>
|
collectionsAll: Array<Maybe<Collection>>
|
||||||
enterChat: EnterChatResult
|
enterChat: ChatResult
|
||||||
getCollabs: Array<Maybe<Collab>>
|
getCollabs: Array<Maybe<Collab>>
|
||||||
getCommunities: Array<Maybe<Community>>
|
getCommunities: Array<Maybe<Community>>
|
||||||
getCommunity: Community
|
getCommunity: Community
|
||||||
getMessages: Array<Maybe<Message>>
|
|
||||||
getShoutBySlug: Shout
|
getShoutBySlug: Shout
|
||||||
getUserCollections: Array<Maybe<Collection>>
|
getUserCollections: Array<Maybe<Collection>>
|
||||||
getUserRoles: Array<Maybe<Role>>
|
getUserRoles: Array<Maybe<Role>>
|
||||||
getUsersBySlugs: Array<Maybe<User>>
|
getUsersBySlugs: Array<Maybe<User>>
|
||||||
isEmailUsed: Scalars['Boolean']
|
isEmailUsed: Scalars['Boolean']
|
||||||
|
loadChat: Array<Maybe<Message>>
|
||||||
|
myChats: Array<Maybe<ChatResult>>
|
||||||
reactionsByAuthor: Array<Maybe<Reaction>>
|
reactionsByAuthor: Array<Maybe<Reaction>>
|
||||||
reactionsByShout: Array<Maybe<Reaction>>
|
reactionsByShout: Array<Maybe<Reaction>>
|
||||||
reactionsForShouts: Array<Maybe<Reaction>>
|
reactionsForShouts: Array<Maybe<Reaction>>
|
||||||
|
@ -349,7 +370,6 @@ export type Query = {
|
||||||
topicsByAuthor: Array<Maybe<Topic>>
|
topicsByAuthor: Array<Maybe<Topic>>
|
||||||
topicsByCommunity: Array<Maybe<Topic>>
|
topicsByCommunity: Array<Maybe<Topic>>
|
||||||
topicsRandom: Array<Maybe<Topic>>
|
topicsRandom: Array<Maybe<Topic>>
|
||||||
userChats: UserChatsResult
|
|
||||||
userFollowedAuthors: Array<Maybe<User>>
|
userFollowedAuthors: Array<Maybe<User>>
|
||||||
userFollowedCommunities: Array<Maybe<Community>>
|
userFollowedCommunities: Array<Maybe<Community>>
|
||||||
userFollowedTopics: Array<Maybe<Topic>>
|
userFollowedTopics: Array<Maybe<Topic>>
|
||||||
|
@ -357,26 +377,14 @@ export type Query = {
|
||||||
userReactedShouts: Array<Maybe<Shout>>
|
userReactedShouts: Array<Maybe<Shout>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type QueryAuthorsAllArgs = {
|
|
||||||
limit: Scalars['Int']
|
|
||||||
offset: Scalars['Int']
|
|
||||||
}
|
|
||||||
|
|
||||||
export type QueryEnterChatArgs = {
|
export type QueryEnterChatArgs = {
|
||||||
chatId: Scalars['String']
|
chatId: Scalars['String']
|
||||||
size?: InputMaybe<Scalars['Int']>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type QueryGetCommunityArgs = {
|
export type QueryGetCommunityArgs = {
|
||||||
slug?: InputMaybe<Scalars['String']>
|
slug?: InputMaybe<Scalars['String']>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type QueryGetMessagesArgs = {
|
|
||||||
chatId: Scalars['String']
|
|
||||||
page: Scalars['Int']
|
|
||||||
size: Scalars['Int']
|
|
||||||
}
|
|
||||||
|
|
||||||
export type QueryGetShoutBySlugArgs = {
|
export type QueryGetShoutBySlugArgs = {
|
||||||
slug: Scalars['String']
|
slug: Scalars['String']
|
||||||
}
|
}
|
||||||
|
@ -397,6 +405,12 @@ export type QueryIsEmailUsedArgs = {
|
||||||
email: Scalars['String']
|
email: Scalars['String']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type QueryLoadChatArgs = {
|
||||||
|
chatId: Scalars['String']
|
||||||
|
page: Scalars['Int']
|
||||||
|
size: Scalars['Int']
|
||||||
|
}
|
||||||
|
|
||||||
export type QueryReactionsByAuthorArgs = {
|
export type QueryReactionsByAuthorArgs = {
|
||||||
limit: Scalars['Int']
|
limit: Scalars['Int']
|
||||||
offset: Scalars['Int']
|
offset: Scalars['Int']
|
||||||
|
@ -759,11 +773,6 @@ export type User = {
|
||||||
wasOnlineAt?: Maybe<Scalars['DateTime']>
|
wasOnlineAt?: Maybe<Scalars['DateTime']>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserChatsResult = {
|
|
||||||
chats?: Maybe<Array<Maybe<Scalars['String']>>>
|
|
||||||
error?: Maybe<Scalars['String']>
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UserNotification = {
|
export type UserNotification = {
|
||||||
id: Scalars['Int']
|
id: Scalars['Int']
|
||||||
kind: Scalars['String']
|
kind: Scalars['String']
|
||||||
|
|
|
@ -4,9 +4,8 @@ import Zine from '../layouts/zine.astro'
|
||||||
import { apiClient } from '../utils/apiClient'
|
import { apiClient } from '../utils/apiClient'
|
||||||
import { initRouter } from '../stores/router'
|
import { initRouter } from '../stores/router'
|
||||||
|
|
||||||
const slug = Astro.params.slug?.toString() || ''
|
const slug = Astro.params.slug?.toString()
|
||||||
|
if (Boolean(slug) === false || slug.includes('/') || slug.includes('.map')) {
|
||||||
if (slug.includes('/') || slug.includes('.map')) {
|
|
||||||
return Astro.redirect('/404')
|
return Astro.redirect('/404')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
src/pages/inbox.astro
Normal file
15
src/pages/inbox.astro
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
import Zine from '../layouts/zine.astro'
|
||||||
|
import { Root } from '../components/Root'
|
||||||
|
import { apiClient } from '../utils/apiClient'
|
||||||
|
import { initRouter } from '../stores/router'
|
||||||
|
|
||||||
|
const chatrooms = await apiClient.getInboxes()
|
||||||
|
|
||||||
|
const { pathname, search } = Astro.url
|
||||||
|
initRouter(pathname, search)
|
||||||
|
---
|
||||||
|
|
||||||
|
<Zine>
|
||||||
|
<Root client:load />
|
||||||
|
</Zine>
|
|
@ -1,13 +0,0 @@
|
||||||
---
|
|
||||||
import InboxPage from '../components/Views/Inbox'
|
|
||||||
import About from '../layouts/about.astro'
|
|
||||||
|
|
||||||
import { initRouter } from '../../stores/router'
|
|
||||||
|
|
||||||
const { pathname, search } = Astro.url
|
|
||||||
initRouter(pathname, search)
|
|
||||||
---
|
|
||||||
|
|
||||||
<About>
|
|
||||||
<InboxPage client:load />
|
|
||||||
</About>
|
|
|
@ -3,7 +3,7 @@ import type { Reaction } from '../../graphql/types.gen'
|
||||||
import { useStore } from '@nanostores/solid'
|
import { useStore } from '@nanostores/solid'
|
||||||
import { apiClient } from '../../utils/apiClient'
|
import { apiClient } from '../../utils/apiClient'
|
||||||
import { reduceBy } from '../../utils/reduce'
|
import { reduceBy } from '../../utils/reduce'
|
||||||
|
// import { roomConnect } from '../../utils/p2p'
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|
||||||
let reactionsOrdered: WritableAtom<Reaction[]>
|
let reactionsOrdered: WritableAtom<Reaction[]>
|
||||||
|
@ -26,8 +26,9 @@ export const loadArticleReactions = async ({
|
||||||
limit?: number
|
limit?: number
|
||||||
offset?: number
|
offset?: number
|
||||||
}): Promise<void> => {
|
}): Promise<void> => {
|
||||||
const resp = await apiClient.getArticleReactions({ articleSlug, limit, offset })
|
const data = await apiClient.getArticleReactions({ articleSlug, limit, offset })
|
||||||
reactionsOrdered.set(resp)
|
// TODO: const [data, provider] = roomConnect(articleSlug, username, "reactions")
|
||||||
|
reactionsOrdered.set(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const loadReactions = async ({
|
export const loadReactions = async ({
|
||||||
|
|
|
@ -30,6 +30,7 @@ import reactionDestroy from '../graphql/mutation/reaction-destroy'
|
||||||
import reactionUpdate from '../graphql/mutation/reaction-update'
|
import reactionUpdate from '../graphql/mutation/reaction-update'
|
||||||
import authorsBySlugs from '../graphql/query/authors-by-slugs'
|
import authorsBySlugs from '../graphql/query/authors-by-slugs'
|
||||||
import incrementView from '../graphql/mutation/increment-view'
|
import incrementView from '../graphql/mutation/increment-view'
|
||||||
|
import myChats from '../graphql/query/my-chats'
|
||||||
|
|
||||||
const log = getLogger('api-client')
|
const log = getLogger('api-client')
|
||||||
|
|
||||||
|
@ -69,9 +70,9 @@ export const apiClient = {
|
||||||
|
|
||||||
return response.data.signIn
|
return response.data.signIn
|
||||||
},
|
},
|
||||||
authRegister: async ({ email, password }): Promise<AuthResult> => {
|
authRegister: async ({ email, password = '', username = '' }): Promise<AuthResult> => {
|
||||||
const response = await publicGraphQLClient
|
const response = await publicGraphQLClient
|
||||||
.mutation(authRegisterMutation, { email, password })
|
.mutation(authRegisterMutation, { email, password, username })
|
||||||
.toPromise()
|
.toPromise()
|
||||||
return response.data.registerUser
|
return response.data.registerUser
|
||||||
},
|
},
|
||||||
|
@ -293,5 +294,8 @@ export const apiClient = {
|
||||||
},
|
},
|
||||||
incrementView: async ({ articleSlug }) => {
|
incrementView: async ({ articleSlug }) => {
|
||||||
await privateGraphQLClient.mutation(incrementView, { shout: articleSlug })
|
await privateGraphQLClient.mutation(incrementView, { shout: articleSlug })
|
||||||
|
},
|
||||||
|
getInboxes: async (payload = {}) => {
|
||||||
|
await privateGraphQLClient.query(myChats, payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
src/utils/p2p.ts
Normal file
41
src/utils/p2p.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { uniqueNamesGenerator, adjectives, animals } from 'unique-names-generator'
|
||||||
|
import { Awareness } from 'y-protocols/awareness'
|
||||||
|
import { WebrtcProvider } from 'y-webrtc'
|
||||||
|
import * as Y from 'yjs'
|
||||||
|
// import type { Reaction } from '../graphql/types.gen'
|
||||||
|
|
||||||
|
export const roomConnect = (
|
||||||
|
room,
|
||||||
|
username = '',
|
||||||
|
keyname = 'reactions'
|
||||||
|
): [Y.XmlFragment, WebrtcProvider] => {
|
||||||
|
const ydoc = new Y.Doc()
|
||||||
|
const yxmlfrag = ydoc.getXmlFragment(keyname) // TODO: encode/decode payload to Reactions[]
|
||||||
|
const webrtcOptions = {
|
||||||
|
awareness: new Awareness(ydoc),
|
||||||
|
filterBcConns: true,
|
||||||
|
maxConns: 33,
|
||||||
|
signaling: [
|
||||||
|
// 'wss://signaling.discours.io',
|
||||||
|
// 'wss://stun.l.google.com:19302',
|
||||||
|
'wss://y-webrtc-signaling-eu.herokuapp.com',
|
||||||
|
'wss://signaling.yjs.dev'
|
||||||
|
],
|
||||||
|
peerOpts: {},
|
||||||
|
password: ''
|
||||||
|
}
|
||||||
|
const provider = new WebrtcProvider(room, ydoc, webrtcOptions)
|
||||||
|
let name = username
|
||||||
|
|
||||||
|
if (Boolean(name) === false) {
|
||||||
|
name = uniqueNamesGenerator({
|
||||||
|
dictionaries: [adjectives, animals],
|
||||||
|
style: 'capital',
|
||||||
|
separator: ' ',
|
||||||
|
length: 2
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
provider.awareness.setLocalStateField('user', { name })
|
||||||
|
return [yxmlfrag, provider]
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
import translate from 'google-translate-api-x'
|
|
||||||
import type { Shout } from '../graphql/types.gen'
|
|
||||||
|
|
||||||
export const translateHook = (aaa, locale) => {
|
|
||||||
if (aaa?.length > 0) {
|
|
||||||
console.log('[zine] articles loaded')
|
|
||||||
if (locale !== 'ru') {
|
|
||||||
// translate titles
|
|
||||||
aaa.forEach((a: Shout) =>
|
|
||||||
translate(a.title, { to: locale.get() }).then((res) => (a.title = res.text))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return aaa
|
|
||||||
}
|
|
|
@ -17,8 +17,5 @@
|
||||||
// Astro will directly run your TypeScript code, no transpilation needed.
|
// Astro will directly run your TypeScript code, no transpilation needed.
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true
|
||||||
},
|
|
||||||
"paths": {
|
|
||||||
"@": ["./src"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user