Skip to content

Commit 6380946

Browse files
Stop persisting shared docs (#175)
This fixes a bug where viewing a shared doc would create a local copy with the same id and redirect to it.
1 parent 6d8ee46 commit 6380946

File tree

7 files changed

+86
-72
lines changed

7 files changed

+86
-72
lines changed

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,18 @@
1717
## Features
1818

1919
- [x] Dark and light themes
20-
- [x] Hybrid markdown rendering
20+
- [x] Hybrid plain-text Markdown rendering
21+
- [x] Syntax highlighting for many common languages (in code blocks)
22+
- [x] Client-side (end-to-end) encryption support
2123
- [x] Cross-platform (desktop and mobile)
22-
- [x] Client-side (end-to-end) encryption
2324
- [x] Offline-first progressive web app
24-
- [x] Tag-based document organization
25+
- [x] Regex full-text search
26+
- [x] Tag-based file organization
27+
- [x] Drag-and-drop or paste to upload files
2528
- [x] Keyboard shortcuts
26-
- [x] Regex search
2729
- [x] Context switching
28-
- [x] Built with modern technologies
30+
- [x] Modern technologies
31+
- [x] Vim Mode support
2932

3033
## Questions
3134

src/App.vue

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<span>Redirecting you to Stripe for checkout</span>
1010
</div>
1111
</div>
12-
<ChangeLog v-if="!home" />
12+
<ChangeLog v-if="!home && !publicDoc" />
1313
<div>
1414
<router-view :inheritAttrs="true" class="flex-grow flex-shrink min-h-0"></router-view>
1515
<div class="flex flex-col min-w-0 max-w-full rounded break-words bg-white notification fixed top-0 right-0 m-4 md:m-2 dark:bg-gray-800" :class="{ 'hidden': !showModal }">
@@ -66,6 +66,12 @@ export default {
6666
ligatures() {
6767
return this.$store.state.settings.editor.ligatures
6868
},
69+
publicDoc() {
70+
return this.$route.name === 'public_doc'
71+
},
72+
showStripeModal() {
73+
return this.$store.state.showStripeModal
74+
},
6975
sizes() {
7076
if (this.mq.current === 'xs') return ['xs xs-plus']
7177
if (this.mq.current === 'sm') return ['sm xs-plus sm-plus']
@@ -75,9 +81,6 @@ export default {
7581
7682
return []
7783
},
78-
showStripeModal() {
79-
return this.$store.state.showStripeModal
80-
},
8184
theme() {
8285
return this.$store.state.settings.theme
8386
},

src/components/Editor.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<div class="gutter h-8 flex-grow" @click="focusEditorEnd"></div>
99
</div>
1010
</div>
11-
<div v-if="!showRightSidebar && text" class="fixed top-4 right-4 z-index-10 hidden md:block">
11+
<div v-if="!readonly && !showRightSidebar && text" class="fixed top-4 right-4 z-index-10 hidden md:block">
1212
<button @click="toggleMeta" class="button button-size-medium button-color-gray">
1313
<svg height="1.25em" width="1.25em" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1414
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
@@ -100,7 +100,9 @@ export default defineComponent({
100100
},
101101
interface: {
102102
appearance: this.appearance,
103+
attribution: false,
103104
images: this.settings.images.enabled,
105+
readonly: this.readonly,
104106
spellcheck: this.settings.spellcheck,
105107
},
106108
selections: this.initialSelections || [],

src/components/TheRightSidebar.vue

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
<span class="ml-3">Hide</span>
1010
</button>
1111
</div>
12-
<div v-if="document" class="flex flex-col flex-grow">
12+
<div v-if="doc" class="flex flex-col flex-grow">
1313
<div>
14-
<DiscardableAction v-if="document.id" :discardedAt="document.discardedAt" :onDiscard="discardDocument" :onRestore="restoreDocument" class="sidebar-button w-full"></DiscardableAction>
14+
<DiscardableAction v-if="doc.id" :discardedAt="doc.discardedAt" :onDiscard="discardDocument" :onRestore="restoreDocument" class="sidebar-button w-full"></DiscardableAction>
1515
<button @click.stop="duplicateDocument" class="sidebar-button w-full">
1616
<svg height="1.25em" width="1.25em" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1717
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2" />
@@ -25,7 +25,7 @@
2525
<span class="ml-6 md:ml-3 flex-grow text-left">Create Sandbox</span>
2626
</button>
2727
<div>
28-
<div v-if="document.public">
28+
<div v-if="doc.public">
2929
<button @click="restrictDocument" class="sidebar-button w-full">
3030
<svg height="1.25em" width="1.25em" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
3131
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
@@ -51,30 +51,30 @@
5151
</div>
5252
</div>
5353
<div class="mt-4">
54-
<TagLink v-for="tag in document.tags" :key="tag" :tag="tag" class="sidebar-link"></TagLink>
54+
<TagLink v-for="tag in doc.tags" :key="tag" :tag="tag" class="sidebar-link"></TagLink>
5555
</div>
5656
<div class="mt-4">
57-
<div v-for="task in document.tasks" class="flex items-center px-3 py-2 my-1 md:px-2 md:py-1">
57+
<div v-for="task in doc.tasks" class="flex items-center px-3 py-2 my-1 md:px-2 md:py-1">
5858
<svg height="1.25em" width="1.25em" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
5959
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
6060
</svg>
6161
<span class="flex-grow overflow-hidden truncate ml-3">{{ task }}</span>
6262
</div>
6363
</div>
6464
<div class="flex flex-col justify-end flex-grow px-3 md:p-2 mt-4 mb-3 md:mb-1">
65-
<div v-if="document.updatedAt">
65+
<div v-if="doc.updatedAt">
6666
<small class="text-gray-700">Last Saved</small>
6767
<div class="capitalize pt-2 md:pt-1">{{ savedAt }}</div>
6868
</div>
69-
<div v-if="document.createdAt" class="mt-3 md:mt-2">
69+
<div v-if="doc.createdAt" class="mt-3 md:mt-2">
7070
<small class="text-gray-700">Created</small>
7171
<div class="pt-2 md:pt-1">{{ createdAt }}</div>
7272
</div>
73-
<div v-if="document.updatedAt" class="mt-3 md:mt-2">
73+
<div v-if="doc.updatedAt" class="mt-3 md:mt-2">
7474
<small class="text-gray-700">Updated</small>
7575
<div class="pt-2 md:pt-1">{{ updatedAt }}</div>
7676
</div>
77-
<div v-if="document.discardedAt" class="mt-3 md:mt-2">
77+
<div v-if="doc.discardedAt" class="mt-3 md:mt-2">
7878
<small class="text-gray-700">Discarded</small>
7979
<div class="pt-2 md:pt-1">{{ discardedAt }}</div>
8080
</div>
@@ -117,44 +117,44 @@ export default {
117117
},
118118
computed: {
119119
codeblocks() {
120-
return parseCodeblocks(this.document.text)
120+
return parseCodeblocks(this.doc.text)
121121
},
122122
createdAt() {
123123
if (this.$route.params.id) {
124-
return moment(this.document.createdAt).format('ddd, MMM Do, YYYY [at] h:mm A')
124+
return moment(this.doc.createdAt).format('ddd, MMM Do, YYYY [at] h:mm A')
125125
}
126126
127127
return 'Not yet created'
128128
},
129129
discardedAt() {
130-
return moment(this.document.discardedAt).format('ddd, MMM Do, YYYY [at] h:mm A')
130+
return moment(this.doc.discardedAt).format('ddd, MMM Do, YYYY [at] h:mm A')
131131
},
132-
document() {
132+
doc() {
133133
return this.$store.getters.currentDoc
134134
},
135135
hasCodeblocks() {
136136
return this.codeblocks.length > 0
137137
},
138138
publicUrl() {
139-
const path = this.$router.resolve({ name: 'shared', params: { id: this.document.id } }).href
139+
const path = this.$router.resolve({ name: 'public_doc', params: { id: this.doc.id } }).href
140140
141141
return `${location.protocol}//${location.host}${path}`
142142
},
143143
savedAt() {
144144
if (this.$route.params.id) {
145-
if (this.now.diff(this.document.updatedAt, 'seconds') < 5) {
145+
if (this.now.diff(this.doc.updatedAt, 'seconds') < 5) {
146146
return 'just now'
147147
}
148148
else {
149-
return `${moment(this.document.updatedAt).from(this.now, true)} ago`
149+
return `${moment(this.doc.updatedAt).from(this.now, true)} ago`
150150
}
151151
}
152152
153153
return 'Not yet saved'
154154
},
155155
updatedAt() {
156156
if (this.$route.params.id) {
157-
return moment(this.document.updatedAt).format('ddd, MMM Do, YYYY [at] h:mm A')
157+
return moment(this.doc.updatedAt).format('ddd, MMM Do, YYYY [at] h:mm A')
158158
}
159159
160160
return 'Not yet updated'
@@ -164,15 +164,15 @@ export default {
164164
async copyPublicUrl() {
165165
// copy link to clipboard
166166
this.$refs.link.select()
167-
document.execCommand('copy')
167+
doc.execCommand('copy')
168168
},
169169
async discardDocument() {
170-
this.$store.dispatch(DISCARD_DOCUMENT, { id: this.document.id })
170+
this.$store.dispatch(DISCARD_DOCUMENT, { id: this.doc.id })
171171
172172
open({ name: 'dashboard' })
173173
},
174174
async duplicateDocument() {
175-
const newDocId = await this.$store.dispatch(DUPLICATE_DOCUMENT, { id: this.document.id })
175+
const newDocId = await this.$store.dispatch(DUPLICATE_DOCUMENT, { id: this.doc.id })
176176
177177
open({ name: 'doc', params: { id: newDocId } })
178178
},
@@ -191,13 +191,13 @@ export default {
191191
CodeSandbox.create(files).then(sandbox_id => CodeSandbox.open(sandbox_id))
192192
},
193193
async restoreDocument() {
194-
this.$store.dispatch(RESTORE_DOCUMENT, { id: this.document.id })
194+
this.$store.dispatch(RESTORE_DOCUMENT, { id: this.doc.id })
195195
},
196196
async restrictDocument() {
197-
this.$store.dispatch(RESTRICT_DOCUMENT, { id: this.document.id })
197+
this.$store.dispatch(RESTRICT_DOCUMENT, { id: this.doc.id })
198198
},
199199
async shareDocument() {
200-
this.$store.dispatch(SHARE_DOCUMENT, { id: this.document.id })
200+
this.$store.dispatch(SHARE_DOCUMENT, { id: this.doc.id })
201201
},
202202
async toggleMeta() {
203203
this.$store.dispatch(SET_RIGHT_SIDEBAR_VISIBILITY, !this.$store.state.showRightSidebar)

src/router.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ export const router = createRouter({
132132
next()
133133
},
134134
},
135+
{
136+
path: 'public/:id',
137+
name: 'public_doc',
138+
component: () => import('/src/views/Editor.vue'),
139+
props: { readonly: true },
140+
},
135141
{
136142
path: 'force-graph',
137143
name: 'force_graph',
@@ -237,11 +243,7 @@ export const router = createRouter({
237243
{
238244
path: 'shared/:id',
239245
name: 'shared',
240-
component: () => import('/src/views/Editor.vue'),
241-
props: {
242-
default: true,
243-
readonly: true,
244-
},
246+
redirect: { name: 'public_doc' },
245247
},
246248
// context switcher
247249
{

src/views/Editor.vue

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<Editor ref="editable" :appearance="appearance" :initialSelections="initialSelections" :settings="settings" :text="doc.text" @input="input" />
2+
<Editor ref="editable" :appearance="appearance" :initialSelections="initialSelections" :readonly="readonly" :settings="settings" :text="doc.text" @input="input" />
33
</template>
44

55
<script>
@@ -105,20 +105,24 @@ export default {
105105
return unpack(packed, { privateKey: this.$store.state.settings.crypto.privateKey })
106106
},
107107
async input(text) {
108-
if (this.id) {
109-
this.$store.dispatch(EDIT_DOCUMENT, { id: this.doc.id, text })
110-
} else {
111-
this.$store.dispatch(ADD_DOCUMENT, new Doc({ id: this.doc.id, text }))
108+
if (!this.readonly) {
109+
// ReadOnly mode means we are viewing a shared doc.
110+
// Todo: Create a new view for shared docs, and store shared docs in a new collection.
111+
if (this.id) {
112+
this.$store.dispatch(EDIT_DOCUMENT, { id: this.doc.id, text })
113+
} else {
114+
this.$store.dispatch(ADD_DOCUMENT, new Doc({ id: this.doc.id, text }))
112115
113-
open({
114-
name: 'doc',
115-
params: {
116-
id: this.doc.id,
117-
props: {
118-
initialSelections: this.$refs.editable.getSelections(),
116+
open({
117+
name: 'doc',
118+
params: {
119+
id: this.doc.id,
120+
props: {
121+
initialSelections: this.$refs.editable.getSelections(),
122+
},
119123
},
120-
},
121-
})
124+
})
125+
}
122126
}
123127
},
124128
},

yarn.lock

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,9 +1140,9 @@
11401140
"@codemirror/stream-parser" "^0.19.0"
11411141

11421142
"@codemirror/language@^0.19.0":
1143-
version "0.19.9"
1144-
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-0.19.9.tgz#9025b88933a05ebb27f16db6f9297b7c069109f0"
1145-
integrity sha512-Rqh7sJduwNVWoLXbOx1nf1vh0zXSIMJ3XDSyISuiIDaOo6Ps7aXgO5BCn+oa3/1RIroEu6vo4PP/zP6B7NSRWg==
1143+
version "0.19.10"
1144+
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-0.19.10.tgz#c3d1330fa5de778c6b6b5177af5572a3d9d596b5"
1145+
integrity sha512-yA0DZ3RYn2CqAAGW62VrU8c4YxscMQn45y/I9sjBlqB1e2OTQLg4CCkMBuMSLXk4xaqjlsgazeOQWaJQOKfV8Q==
11461146
dependencies:
11471147
"@codemirror/state" "^0.19.0"
11481148
"@codemirror/text" "^0.19.0"
@@ -1634,9 +1634,9 @@
16341634
integrity sha512-9FqhNjKQWpQ3fGnSOCovHOm+yhhiorKEqYLAfd525jWavunDJcx8rOW6i6ozAh+FbwcYMkL7b+3j4UR/30MpoQ==
16351635

16361636
"@grpc/grpc-js@^1.3.2":
1637-
version "1.5.10"
1638-
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.5.10.tgz#12f0b33b338fad5a0e48ee1d5999b5b08da60bcc"
1639-
integrity sha512-++oAubX/7rJzlqH0ShyzDENNNDHYrlttdc3NM40KlaVQDcgGqQknuPoavmyTC+oNUDyxPCX5dHceKhfcgN3tiw==
1637+
version "1.6.0"
1638+
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.6.0.tgz#b9616121fdff6b2fa21011be96e35f03e57a5c78"
1639+
integrity sha512-KwNibKGx1qmAwsrYu75FhUo3+m6GMJoBfdnYZte9YQ2EM3hZ5Ez+8+Q+FAMONtfU0XJGUkGK5S+q4CXSjx5Ahw==
16401640
dependencies:
16411641
"@grpc/proto-loader" "^0.6.4"
16421642
"@types/node" ">=12.12.47"
@@ -2105,9 +2105,9 @@
21052105
integrity sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==
21062106

21072107
"@writewithocto/ink@^0.6.2":
2108-
version "0.6.8"
2109-
resolved "https://registry.yarnpkg.com/@writewithocto/ink/-/ink-0.6.8.tgz#5247154817f11576c119411da12669394ffd73e6"
2110-
integrity sha512-vb98qwEPQenn5wkuwekqxhjj11tHVHcEH+DELJy3pYgrRhHj283OxkFhqeHOLeT0Jpfjka+bBfoeHVpdKlkrBQ==
2108+
version "0.6.9"
2109+
resolved "https://registry.yarnpkg.com/@writewithocto/ink/-/ink-0.6.9.tgz#3d6e6b2d9237c345de87723def4dfa9a2f80b890"
2110+
integrity sha512-t8Dww4BHHf1kc4fC2pvG6UvYwC4beFEYXEYlQ3q67/TAccp6H1PbEmlO2+3Dmyw66uBa7dsk2QLmPKWiRAsbqg==
21112111
dependencies:
21122112
"@codemirror/commands" "^0.19.0"
21132113
"@codemirror/comment" "^0.19.0"
@@ -2127,9 +2127,9 @@
21272127
is-plain-object "^5.0.0"
21282128

21292129
"@writewithocto/vue-ink@^0.6.0":
2130-
version "0.6.4"
2131-
resolved "https://registry.yarnpkg.com/@writewithocto/vue-ink/-/vue-ink-0.6.4.tgz#15dd6d2d06503b8d025121dcea60964dd9777aeb"
2132-
integrity sha512-d7LIw5eS8gubkjYr0huags1+vQHlqUTI8RTlGmoIeX8Zs+dARsZnaxgUvG4meDTk3BgXZNn3rNPSZC2NUdF63g==
2130+
version "0.6.5"
2131+
resolved "https://registry.yarnpkg.com/@writewithocto/vue-ink/-/vue-ink-0.6.5.tgz#6449741355fce455dc98657f5f5f2eb915e35801"
2132+
integrity sha512-QLFR8ispzH1xRY8cGHQHiGdlpBgyhhWpuu6st36qZ1LxFaY9w+kRZNaX1c6ClDkdfokyFxc8Y1TYMgIXcWwxig==
21332133
dependencies:
21342134
"@writewithocto/ink" "^0.6.2"
21352135
vue "^3.2.31"
@@ -2558,9 +2558,9 @@ can-use-dom@^0.1.0:
25582558
integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=
25592559

25602560
caniuse-lite@^1.0.30001317:
2561-
version "1.0.30001322"
2562-
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001322.tgz#2e4c09d11e1e8f852767dab287069a8d0c29d623"
2563-
integrity sha512-neRmrmIrCGuMnxGSoh+x7zYtQFFgnSY2jaomjU56sCkTA6JINqQrxutF459JpWcWRajvoyn95sOXq4Pqrnyjew==
2561+
version "1.0.30001323"
2562+
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001323.tgz#a451ff80dec7033016843f532efda18f02eec011"
2563+
integrity sha512-e4BF2RlCVELKx8+RmklSEIVub1TWrmdhvA5kEUueummz1XyySW0DVk+3x9HyhU9MuWTa2BhqLgEuEmUwASAdCA==
25642564

25652565
canvas-color-tracker@1:
25662566
version "1.1.5"
@@ -2633,9 +2633,9 @@ chownr@^2.0.0:
26332633
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
26342634

26352635
clean-css@^5.2.2:
2636-
version "5.2.4"
2637-
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4"
2638-
integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==
2636+
version "5.3.0"
2637+
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.0.tgz#ad3d8238d5f3549e83d5f87205189494bc7cbb59"
2638+
integrity sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==
26392639
dependencies:
26402640
source-map "~0.6.0"
26412641

@@ -6103,9 +6103,9 @@ vite-plugin-pwa@^0.11.2:
61036103
workbox-window "^6.4.2"
61046104

61056105
vite@^2.5.10:
6106-
version "2.9.0"
6107-
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.0.tgz#4417ce84a09d93c9e5a796b296285bc2f75d6c41"
6108-
integrity sha512-5NAnNqzPmZzJvrswZGeTS2JHrBGIzIWJA2hBTTMYuoBVEMh0xwE0b5yyIXFxf7F07hrK4ugX2LJ7q6t7iIbd4Q==
6106+
version "2.9.1"
6107+
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.1.tgz#84bce95fae210a7beb566a0af06246748066b48f"
6108+
integrity sha512-vSlsSdOYGcYEJfkQ/NeLXgnRv5zZfpAsdztkIrs7AZHV8RCMZQkwjo4DS5BnrYTqoWqLoUe1Cah4aVO4oNNqCQ==
61096109
dependencies:
61106110
esbuild "^0.14.27"
61116111
postcss "^8.4.12"

0 commit comments

Comments
 (0)