Merge to master (#445)

* Fix/venus spanish (#423)

fix: update venus spanish language

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>

* fix: can not convert url text to link after paste

* fix: double link icon size error

* feat(code): enhance markdown parse code

* fix(code): add robust

* fix: remove special menu

* chore: clean code

* fix: ime with command menu

* fix(code): langs[lang] is not a function

* fix: can't add image and delete more action button (#430)

* feat: add zh_Hant for venus (#431)

* fix: lang select in  code block is insanity

* GitHub Doc Updates (#421)

* Update types-of-contributions.md

* Update README.md

Tidy up links section

* fix: inline menu position (#433)

* Master (#436)

* Fix/venus spanish (#423) (#425)

fix: update venus spanish language

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>

* Merge to master (#435)

* Fix/venus spanish (#423)

fix: update venus spanish language

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>

* fix: can not convert url text to link after paste

* fix: double link icon size error

* feat(code): enhance markdown parse code

* fix(code): add robust

* fix: remove special menu

* chore: clean code

* fix: ime with command menu

* fix(code): langs[lang] is not a function

* fix: can't add image and delete more action button (#430)

* feat: add zh_Hant for venus (#431)

* fix: lang select in  code block is insanity

* GitHub Doc Updates (#421)

* Update types-of-contributions.md

* Update README.md

Tidy up links section

* fix: inline menu position (#433)

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: QiShaoXuan <qishaoxuan777@gmail.com>
Co-authored-by: tzhangchi <terry.zhangchi@outlook.com>
Co-authored-by: lawvs <18554747+lawvs@users.noreply.github.com>
Co-authored-by: DiamondThree <diamond.shx@gmail.com>
Co-authored-by: CJSS <CJSS@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: QiShaoXuan <qishaoxuan777@gmail.com>
Co-authored-by: tzhangchi <terry.zhangchi@outlook.com>
Co-authored-by: lawvs <18554747+lawvs@users.noreply.github.com>
Co-authored-by: DiamondThree <diamond.shx@gmail.com>
Co-authored-by: CJSS <CJSS@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>

* fix: close select popover after mouse leave code block

* docs: add jobs

* docs: update job docs structure

* fix: typo

* Update affine.pro.md

* Update affine.pro.md

* Update affine.pro.md

* feat: add Serbian language to venus (#441)

* refactor: redesign loading workspace db

* chore: remove unuse site logic

* feat: affine-embed-header

* Update affine.pro.md

* feat: add German language to venus (#443)

* fix: connection state

* refactor: jd

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: QiShaoXuan <qishaoxuan777@gmail.com>
Co-authored-by: tzhangchi <terry.zhangchi@outlook.com>
Co-authored-by: lawvs <18554747+lawvs@users.noreply.github.com>
Co-authored-by: DiamondThree <diamond.shx@gmail.com>
Co-authored-by: CJSS <CJSS@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>
Co-authored-by: DarkSky <darksky2048@gmail.com>
Co-authored-by: HeJiachen-PM <79301703+HeJiachen-PM@users.noreply.github.com>
This commit is contained in:
zuomeng wang
2022-09-21 15:45:40 +08:00
committed by GitHub
parent c010e05023
commit ef707b95ef
18 changed files with 194 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
FROM node:16-alpine as builder
ARG HUBSPOT_API_SECRET
ARG AFFINE_EMBED_HEADER
WORKDIR /app
RUN apk add git && npm i -g pnpm@7
COPY . .

View File

@@ -71,7 +71,7 @@ jobs:
tags: ${{ env.LOCAL_CACHE }}
target: AFFiNE
build-args: |
HUBSPOT_API_SECRET=${{ secrets.HUBSPOT_API_SECRET }}
AFFINE_EMBED_HEADER=${{ secrets.AFFINE_EMBED_HEADER }}
- name: Build and push Docker image (AFFINE-Local)
uses: docker/build-push-action@v3

View File

@@ -135,7 +135,7 @@ We use the following open source projects to help us build a better development
Thanks a lot to the community for providing such powerful and simple libraries, so that we can focus more on the implementation of the product logic, and we hope that in the future our projects will also provide a more easy-to-use knowledge base for everyone.
You enjoy AFFiNE? You are not alone. [Some amazing companies](./docs/Jobs.md) are looking for developers with some AFFiNE and/or AFFiNE technology experience.
[Some amazing companies](./docs/jobs/summary.md), including AFFiNE are looking for developers! Are you interested in helping build with AFFiNE and/or its partners? Check out some of the latest [jobs available](./docs/jobs/summary.md).
# Contributors

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title><%= htmlWebpackPlugin.options.title %></title>
<%= htmlWebpackPlugin.options.hubspotScript %>
<%= htmlWebpackPlugin.options.embedHeaderScript %>
</head>
<body>
<div id="root"></div>

View File

@@ -11,13 +11,7 @@ const TerserPlugin = require('terser-webpack-plugin');
const Style9Plugin = require('style9/webpack');
const enableBundleAnalyzer = process.env.BUNDLE_ANALYZER;
function generateHubspotScript() {
const hubspotApiSecret = process.env.HUBSPOT_API_SECRET;
if (hubspotApiSecret) {
return `<script type="text/javascript" id="hs-script-loader" async defer src="//js-na1.hs-scripts.com/${hubspotApiSecret}.js"></script>`;
}
}
const embedHeaderScript = process.env.AFFINE_EMBED_HEADER;
module.exports = function (webpackConfig) {
const config = getNxWebpackConfig(webpackConfig);
@@ -185,7 +179,7 @@ module.exports = function (webpackConfig) {
), //favicon path
template: path.resolve(__dirname, './src/template.html'),
publicPath: '/',
hubspotScript: generateHubspotScript(),
embedHeaderScript,
}),
new Style9Plugin(),
isProd &&

View File

@@ -0,0 +1,39 @@
{
"Blog": "Blog",
"AboutUs": "Über uns",
"Open Source": "Open Source",
"Docs": "Dokumentation",
"Feedback": "Feedback",
"ContactUs": "Kontaktiere uns",
"Privacy First": "Privatsphären-respektierend",
"Alternative": "Alternative",
"Check GitHub": "Weitere Informationen befinden sich auf Github",
"GitHub": "GitHub",
"Try it Online": "Teste es online",
"language": "Sprache",
"description1": {
"part1": "Affine ist die gemeinschaftliche Wissensdatenbank der nächsten Generation für Profis.",
"part2": "Es ist nicht nur eine Sammlung von Dokumenten, Whiteboards und Tabellen.",
"part3": "Ändere jeden Block, wie du ihn gerne hättest.",
"part4": "Verabschiede dich von Redundanz. Speichere deine Daten einmalig und behalte sie wie du sie gerne hättest."
},
"description2": {
"part1": "Gestalte deine Seite",
"part2": "Dokumente, Kanbans und Datenbanken sind voll funktional - immer und überall. Eine wahrhaftige \"Was du siehst, ist das, was du bekommst.\"-Umgebung,",
"part3": "Alle Seiten können wahlweise in einer Dokumenten- (Paper Mode) und einer Whiteboard-Ansicht (Edge less Mode) angezeigt werden."
},
"description3": {
"part1": "Plane deine Aufgabe",
"part2": "Kein Chaos mehr bei der Verwaltung mehrerer Ansichten.",
"part3": "Erstelle eine TODO Listenelement und bearbeite es nahtlos in einem Kanban.",
"part4": "Die Verwaltung von mehrdimensionalen Tabellen sollte einfach sein - und ist es jetzt auch."
},
"description4": {
"part1": "Der Respekt deiner Privatsphäre und Zusammenarbeit stehen an erster Stelle. Keine Kompromisse.",
"part2": "Wir lassen uns nicht gerne einschränken, und das sollten Sie auch nicht. Der Schutz der Privatsphäre ist die Grundlage für alles, was wir tun, aber sie sollte uns nicht aufhalten - deshalb gibt es keine Kompromisse.",
"part3": "Ihre Daten gehören Ihnen; sie sind immer lokal gespeichert und gesichert und stehen Ihnen jederzeit zur Verfügung. Gleichzeitig können Sie die Funktionen für die Zusammenarbeit nutzen, z. B. die Bearbeitung in Echtzeit und die gemeinsame Nutzung mit anderen, ohne dass eine Cloud eingerichtet werden muss."
},
"BuildFor": "Build for an open and semantic future",
"KeepUpdated": "Keep Updated on",
"Join": "Join Our Community"
}

View File

@@ -1,7 +1,9 @@
import de from './de.json';
import en from './en.json';
import es from './es.json';
import zh_Hans from './zh.json';
import sr from './sr.json';
import zh_Hant from './zh-Hant.json';
import zh_Hans from './zh.json';
export const LOCALES = [
{
@@ -28,4 +30,16 @@ export const LOCALES = [
originalName: 'español',
res: es,
},
{
name: 'Serbian',
tag: 'sr',
originalName: 'српски',
res: sr,
},
{
name: 'German',
tag: 'de',
originalName: 'Deutsch',
res: de,
},
] as const;

View File

@@ -0,0 +1,39 @@
{
"Blog": "Blog",
"AboutUs": "O nama",
"Open Source": "Otvoreni kod",
"Docs": "Dokumenti",
"Feedback": "Povratne informacije",
"ContactUs": "Kontaktirajte nas",
"Privacy First": "Privatnost na prvom mestu",
"Alternative": "Alternativa",
"Check GitHub": "Proveri GitHub",
"GitHub": "GitHub",
"Try it Online": "Probaj onlajn",
"language": "Jezik",
"description1": {
"part1": "Affine je baza znanja sledeće generacije za profesionalce koja omogućava timski rad.",
"part2": "Nije samo zbirka dokumenata, panela i tabela.",
"part3": "Promeni svaki elemenat po svojoj želji.",
"part4": "Bez nepotrebnosti. Sačuvaj svoje podatke jednom, i čuvaj ih onako kako ti to želiš."
},
"description2": {
"part1": "Oblikuj svoju stranicu",
"part2": "Dokumenti, Kanban-table i baze podataka su potpuno funkcionalne bilo kad i bilo gde. Prava ovo-što-vidiš-je-ono-što-dobijaš sredina za tvoje podatke.",
"part3": "Sve stranice dolaze sa dokument-izgledom (Papirni način rada) i panel-izgledom (Bezokvirni način rada)."
},
"description3": {
"part1": "Planiraj svoje zadatke",
"part2": "Nema više haosa nastalog pri upravljanju višestrukim izgledima.",
"part3": "Kreiraj TODO listu u Markdown i jednostavno je prilagođavaj u Kanban prikazu.",
"part4": "Upravljanje multidimenzionalnim tabelama bi trebalo biti jednostavno, a sada i jeste."
},
"description4": {
"part1": "Privatnost i timski rad na prvom mestu. Bez kompromisa bez obzira na sve.",
"part2": "Ne volimo biti zatvoreni, a ne bi trebali to ni Vi. Privatnost je osnova svega što radimo, ali nas ona ne bi smela ni ograničavati i zato nema kompromisa.",
"part3": "Vaši podaci su vaši; čuvaju se lokalno na Vašem računaru i uvek su Vam dostupni. Pritom ipak možete uživati u prednostima saradnje kao što su uređivanje i deljenje dokumenata u stvarnom vremenu s drugima, bez ikakvog postavljanja onlajn oblaka."
},
"BuildFor": "Stvoreno za otvorenu i semantičku budućnost",
"KeepUpdated": "Ažuriraj",
"Join": "Pridruži se zajednici"
}

View File

@@ -1,5 +0,0 @@
# Jobs
- [<b>Full Stack Platform Engineer</b>](./mysc.app.md) @[mysc.app](https://mysc.app/)
Rust · GWST · Remote · Shanghai, China

50
docs/jobs/affine.pro.md Normal file
View File

@@ -0,0 +1,50 @@
## Fullstack Engineer
The **AFFiNE** 's vision is to scale 100000+ organizations' teams and businesses faster and more efficiently.
We're hiring for multiple Fullstack Engineer positions across the building-blocks sub-team. The **building-blocks** team works to create the best **block-editor** and **open-block** protocol for AFFiNE Customers. This means people can manage their businesses and teams by AFFiNE.
## The work
### Below is a selection of the initiatives that you may work on:
- Contribute to **AFFiNE Open-Source**, including documents and code
- Improve provisioning and onboarding of new sales-assisted affine.com subscribers
- Improvement to Pager Editor and Edgeless Editor
- Improvement to Billable Members
- Research feedback for future-dated amendments in Subscription Admin
At AFFiNE, developers are independent and self-organized individual contributors who work together as a tight team in a remote and agile way.
### What will you bring
- Professional software engineering experience with **editor** or **graphics** in large production environments
- Experience and proficiency in Rust, Go, or Java
- Production experience with JavaScript
- Significant experience with **React (ideal)**, Vue, and/or Angular.
- Significant experience with CSS, HTML semantics, and accessibility
- You have strong written communication skills
- You have demonstrated the ability to onboard and integrate with an organization long-term.
- You are comfortable working in a cross-functional organization
- You are able to use AFFiNE or productivity products
- You share our values and work in accordance with those values
It would be great if you have
- Experience with license or subscription management
- Experience with SaaS billing
- Experience or familiarity with open source
- Experience with the AFFiNE product as a user or contributor
- Experience working with **a remote team**
- Enterprise software company experience
- Experience scaling **a successful SaaS product**
- Developer platform/tool industry experience
- Experience working with **a global team**
### What we offer
- Humanized office equipment (MacBook pro + iPad Air + ergonomic chair, lift table), equipment purchase authorization of $2800
- Except for public holidays, the annual paid annual leave is 12 working days, which can be increased year by year according to the working hours;
- Statutory holidays are not commuted, and additional 7+ holidays are obtained every year;
- Free lunch with gradually increasing meal standard;
- Travel and rent subsidies are customized according to individual needs;
- Unlimited drinks and snacks;
- Free IELTS test open to all employees;
- Flexible and optional social security and provident fund payment locations
- Become a maintainer of great open source projects and use Copilot powered by Github for free

9
docs/jobs/summary.md Normal file
View File

@@ -0,0 +1,9 @@
# Jobs
- [<b>Fullstack Engineer</b>](./affine.pro.md) @[affine.pro](http://affine.pro/)
Rust ·TS · Virgo · JWST · Remote , Global
- [<b>Full Stack Platform Engineer</b>](./mysc.app.md) @[mysc.app](https://mysc.app/)
Rust · JWST · Remote · Shanghai, China

View File

@@ -153,6 +153,7 @@ export const CodeView = ({ block, editor }: CreateCodeView) => {
const langType: string = block.getProperty('lang');
const [extensions, setExtensions] = useState<Extension[]>();
const [showOperationPanel, setShowOperationPanel] = useState(false);
const [selectOpen, setSelectOpen] = useState(false);
const isSelecting = useRef(false);
const codeMirror = useRef<ReactCodeMirrorRef>();
const focusCode = () => {
@@ -197,6 +198,7 @@ export const CodeView = ({ block, editor }: CreateCodeView) => {
setShowOperationPanel(true);
}}
onMouseLeave={() => {
setSelectOpen(false);
!isSelecting.current && setShowOperationPanel(false);
}}
>
@@ -210,9 +212,11 @@ export const CodeView = ({ block, editor }: CreateCodeView) => {
onChange={(selectedValue: string) => {
handleLangChange(selectedValue);
}}
onListboxOpenChange={() => {
onListboxOpenChange={open => {
setSelectOpen(open);
isSelecting.current = true;
}}
open={selectOpen}
>
{Object.keys(langs).map(item => {
return (

View File

@@ -5,6 +5,7 @@ import {
type ForwardedRef,
type ReactNode,
type RefAttributes,
useEffect,
} from 'react';
/* eslint-disable no-restricted-imports */
import SelectUnstyled, {
@@ -15,13 +16,13 @@ import SelectUnstyled, {
import PopperUnstyled from '@mui/base/PopperUnstyled';
import { ArrowDropDownIcon } from '@toeverything/components/icons';
import { styled } from '../styled';
type ExtendSelectProps = {
// Width is always used custom, it will be set to root button and popover
width?: number | string;
style?: CSSProperties;
listboxStyle?: CSSProperties;
placeholder?: ReactNode;
open?: boolean;
};
/**
@@ -40,7 +41,6 @@ export const Select = forwardRef(function CustomSelect<TValue>(
props: ExtendSelectProps & SelectUnstyledProps<TValue>,
ref: ForwardedRef<HTMLUListElement>
) {
const [isOpen, setIsOpen] = useState(false);
const {
width = '100%',
style,
@@ -48,7 +48,11 @@ export const Select = forwardRef(function CustomSelect<TValue>(
placeholder,
onListboxOpenChange,
onChange,
open: propsOpen,
} = props;
const openControlledByProps = propsOpen !== undefined;
const [isOpen, setIsOpen] = useState(false);
const components: SelectUnstyledProps<TValue>['components'] = {
// Root: generateStyledRoot({ width, ...style }),
Root: forwardRef((rootProps, rootRef) => {
@@ -88,13 +92,13 @@ export const Select = forwardRef(function CustomSelect<TValue>(
return (
<SelectUnstyled
{...props}
listboxOpen={isOpen}
listboxOpen={openControlledByProps ? propsOpen : isOpen}
onListboxOpenChange={open => {
setIsOpen(open);
!openControlledByProps && setIsOpen(open);
onListboxOpenChange?.(open);
}}
onChange={v => {
setIsOpen(false);
!openControlledByProps && setIsOpen(false);
onChange?.(v);
}}
ref={ref}

View File

@@ -8,21 +8,12 @@ import {
BlockMatcher,
Connectivity,
} from '@toeverything/datasource/jwt';
import { sleep } from '@toeverything/utils';
import type { ObserveCallback, ReturnUnobserve } from './observer';
import { getObserverName, ObserverManager } from './observer';
export type { ObserveCallback, ReturnUnobserve } from './observer';
const workspaces: Record<string, BlockClientInstance> = {};
const loading = new Set();
const waitLoading = async (key: string) => {
while (loading.has(key)) {
await sleep(50);
}
};
const workspaces: Record<string, Promise<BlockClientInstance>> = {};
async function _getCurrentToken() {
if (!process.env['NX_LOCAL']) {
@@ -48,20 +39,15 @@ async function _getBlockDatabase(
workspace: string,
options?: BlockInitOptions
) {
if (loading.has(workspace)) {
await waitLoading(workspace);
}
if (!workspaces[workspace]) {
loading.add(workspace);
workspaces[workspace] = await BlockClient.init(workspace, {
enabled: _enabled[workspace] || ['idb'],
...options,
token: await _getCurrentToken(),
});
workspaces[workspace] = _getCurrentToken().then(token =>
BlockClient.init(workspace, {
enabled: _enabled[workspace] || ['idb'],
...options,
token,
})
);
(window as any).client = workspaces[workspace];
await workspaces[workspace].buildIndex();
loading.delete(workspace);
}
return workspaces[workspace];
}

View File

@@ -641,7 +641,7 @@ export class BlockClient<
const { importData, exportData, hasExporter, installExporter } =
getDataExporter();
const instance = await YjsAdapter.init(workspace, {
const yjsAdapter = await YjsAdapter.init(workspace, {
provider: getYjsProviders({
enabled: [],
backend: BucketBackend.YjsWebSocketAffine,
@@ -652,10 +652,17 @@ export class BlockClient<
}),
...options,
});
return new BlockClient(instance, workspace, {
...options,
installExporter,
});
const blockClient: BlockClientInstance = new BlockClient(
yjsAdapter,
workspace,
{
...options,
installExporter,
}
);
await blockClient.buildIndex();
return blockClient;
}
}

View File

@@ -16,9 +16,7 @@ function getLocation() {
function getCollaborationPoint() {
const { protocol, host } = getLocation();
const ws = protocol.startsWith('https') ? 'wss' : 'ws';
const isOnline = host.endsWith('affine.pro');
const site = isOnline ? host : 'localhost:3000';
return `${ws}://${site}/collaboration/`;
return `${ws}://${host}/collaboration/`;
}
export const BucketBackend = {

View File

@@ -118,7 +118,7 @@ export const getYjsProviders = (
// TODO: synced will also be triggered on reconnection after losing sync
// There needs to be an event mechanism to emit the synchronization state to the upper layer
ws.once('synced', () => resolve());
ws.once('lost-connection', () => resolve());
ws.once('lost-connection', () => reject());
ws.once('connection-error', () => reject());
ws.on('synced', () => instances.emitState('connected'));
ws.on('lost-connection', () =>