mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 10:16:26 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
789926bc76 | ||
|
|
006795b4d0 | ||
|
|
3e5d78d322 | ||
|
|
58c4a78be1 | ||
|
|
2603dfc1ed | ||
|
|
2df590600b | ||
|
|
ef20a8f3e5 | ||
|
|
3e405e1abf | ||
|
|
553832bdfa | ||
|
|
18d65d999a | ||
|
|
3b5eff582a | ||
|
|
85d09b3b3d | ||
|
|
8958e67fcf |
@@ -63,7 +63,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.focusHandler = () => {
|
this.focusHandler = () => {
|
||||||
ipcRenderer.send('editor:focused', true)
|
ipcRenderer.send('editor:focused', true)
|
||||||
}
|
}
|
||||||
const debouncedDeletionOfAttachments = _.debounce(
|
this.debouncedDeletionOfAttachments = _.debounce(
|
||||||
attachmentManagement.deleteAttachmentsNotPresentInNote,
|
attachmentManagement.deleteAttachmentsNotPresentInNote,
|
||||||
30000
|
30000
|
||||||
)
|
)
|
||||||
@@ -80,7 +80,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.props.onBlur != null && this.props.onBlur(e)
|
this.props.onBlur != null && this.props.onBlur(e)
|
||||||
const { storageKey, noteKey } = this.props
|
const { storageKey, noteKey } = this.props
|
||||||
if (this.props.deleteUnusedAttachments === true) {
|
if (this.props.deleteUnusedAttachments === true) {
|
||||||
debouncedDeletionOfAttachments(
|
this.debouncedDeletionOfAttachments(
|
||||||
this.editor.getValue(),
|
this.editor.getValue(),
|
||||||
storageKey,
|
storageKey,
|
||||||
noteKey
|
noteKey
|
||||||
@@ -810,6 +810,8 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleChange(editor, changeObject) {
|
handleChange(editor, changeObject) {
|
||||||
|
this.debouncedDeletionOfAttachments.cancel()
|
||||||
|
|
||||||
spellcheck.handleChange(editor, changeObject)
|
spellcheck.handleChange(editor, changeObject)
|
||||||
|
|
||||||
// The current note contains an toc. We'll check for changes on headlines.
|
// The current note contains an toc. We'll check for changes on headlines.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import markdownItTocAndAnchor from '@hikerpig/markdown-it-toc-and-anchor'
|
|||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import katex from 'katex'
|
import katex from 'katex'
|
||||||
import { lastFindInArray } from './utils'
|
import { escapeHtmlCharacters, lastFindInArray } from './utils'
|
||||||
|
|
||||||
function createGutter(str, firstLineNumber) {
|
function createGutter(str, firstLineNumber) {
|
||||||
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1
|
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1
|
||||||
@@ -479,6 +479,16 @@ class Markdown {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.md.renderer.rules.code_inline = function(tokens, idx) {
|
||||||
|
const token = tokens[idx]
|
||||||
|
|
||||||
|
return (
|
||||||
|
'<code class="inline">' +
|
||||||
|
escapeHtmlCharacters(token.content) +
|
||||||
|
'</code>'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (config.preview.smartArrows) {
|
if (config.preview.smartArrows) {
|
||||||
this.md.use(smartArrows)
|
this.md.use(smartArrows)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { getLocales } from 'browser/lib/Languages'
|
|||||||
import applyShortcuts from 'browser/main/lib/shortcutManager'
|
import applyShortcuts from 'browser/main/lib/shortcutManager'
|
||||||
import { chooseTheme, applyTheme } from 'browser/main/lib/ThemeManager'
|
import { chooseTheme, applyTheme } from 'browser/main/lib/ThemeManager'
|
||||||
import { push } from 'connected-react-router'
|
import { push } from 'connected-react-router'
|
||||||
|
import { ipcRenderer } from 'electron'
|
||||||
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
@@ -184,6 +185,7 @@ class Main extends React.Component {
|
|||||||
this.toggleMenuBarVisible.bind(this)
|
this.toggleMenuBarVisible.bind(this)
|
||||||
)
|
)
|
||||||
eventEmitter.on('dispatch:push', this.changeRoutePush.bind(this))
|
eventEmitter.on('dispatch:push', this.changeRoutePush.bind(this))
|
||||||
|
eventEmitter.on('update', () => ipcRenderer.send('update-check', 'manual'))
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import DevTools from './DevTools'
|
|||||||
require('./lib/ipcClient')
|
require('./lib/ipcClient')
|
||||||
require('../lib/customMeta')
|
require('../lib/customMeta')
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import ConfigManager from './lib/ConfigManager'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
|
|
||||||
@@ -107,6 +108,22 @@ function updateApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function downloadUpdate() {
|
||||||
|
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
|
type: 'warning',
|
||||||
|
message: i18n.__('Update Boostnote'),
|
||||||
|
detail: i18n.__('New Boostnote is ready to be downloaded.'),
|
||||||
|
buttons: [i18n.__('Download now'), i18n.__('Ignore updates')]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (index === 0) {
|
||||||
|
ipcRenderer.send('update-download-confirm')
|
||||||
|
} else if (index === 1) {
|
||||||
|
ipcRenderer.send('update-cancel')
|
||||||
|
ConfigManager.set({ autoUpdateEnabled: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ConnectedRouter history={history}>
|
<ConnectedRouter history={history}>
|
||||||
@@ -147,8 +164,12 @@ ReactDOM.render(
|
|||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.on('update-found', function() {
|
ipcRenderer.on('update-found', function() {
|
||||||
notify('Update found!', {
|
downloadUpdate()
|
||||||
body: 'Preparing to update...'
|
})
|
||||||
|
|
||||||
|
ipcRenderer.on('update-not-found', function(_, msg) {
|
||||||
|
notify('Update not found!', {
|
||||||
|
body: msg
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ const DEFAULT_MARKDOWN_LINT_CONFIG = `{
|
|||||||
|
|
||||||
const DEFAULT_CSS_CONFIG = `
|
const DEFAULT_CSS_CONFIG = `
|
||||||
/* Drop Your Custom CSS Code Here */
|
/* Drop Your Custom CSS Code Here */
|
||||||
[data-theme="default"] p code,
|
[data-theme="default"] p code.inline,
|
||||||
[data-theme="default"] li code,
|
[data-theme="default"] li code.inline,
|
||||||
[data-theme="default"] td code
|
[data-theme="default"] td code.inline
|
||||||
{
|
{
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
|
|||||||
@@ -638,74 +638,74 @@ code {
|
|||||||
direction: ltr;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
|
|
||||||
p code,
|
p code.inline,
|
||||||
li code,
|
li code.inline,
|
||||||
td code
|
td code.inline
|
||||||
{
|
{
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
[data-theme="default"] p code,
|
[data-theme="default"] p code.inline,
|
||||||
[data-theme="default"] li code,
|
[data-theme="default"] li code.inline,
|
||||||
[data-theme="default"] td code
|
[data-theme="default"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #F4F4F4;
|
background-color: #F4F4F4;
|
||||||
border-color: #d9d9d9;
|
border-color: #d9d9d9;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
[data-theme="white"] p code,
|
[data-theme="white"] p code.inline,
|
||||||
[data-theme="white"] li code,
|
[data-theme="white"] li code.inline,
|
||||||
[data-theme="white"] td code
|
[data-theme="white"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #F4F4F4;
|
background-color: #F4F4F4;
|
||||||
border-color: #d9d9d9;
|
border-color: #d9d9d9;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
[data-theme="dark"] p code,
|
[data-theme="dark"] p code.inline,
|
||||||
[data-theme="dark"] li code,
|
[data-theme="dark"] li code.inline,
|
||||||
[data-theme="dark"] td code
|
[data-theme="dark"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
border-color: #555;
|
border-color: #555;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
[data-theme="dracula"] p code,
|
[data-theme="dracula"] p code.inline,
|
||||||
[data-theme="dracula"] li code,
|
[data-theme="dracula"] li code.inline,
|
||||||
[data-theme="dracula"] td code
|
[data-theme="dracula"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
border-color: #555;
|
border-color: #555;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
[data-theme="monokai"] p code,
|
[data-theme="monokai"] p code.inline,
|
||||||
[data-theme="monokai"] li code,
|
[data-theme="monokai"] li code.inline,
|
||||||
[data-theme="monokai"] td code
|
[data-theme="monokai"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
border-color: #555;
|
border-color: #555;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
[data-theme="nord"] p code,
|
[data-theme="nord"] p code.inline,
|
||||||
[data-theme="nord"] li code,
|
[data-theme="nord"] li code.inline,
|
||||||
[data-theme="nord"] td code
|
[data-theme="nord"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
border-color: #555;
|
border-color: #555;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
[data-theme="solarized-dark"] p code,
|
[data-theme="solarized-dark"] p code.inline,
|
||||||
[data-theme="solarized-dark"] li code,
|
[data-theme="solarized-dark"] li code.inline,
|
||||||
[data-theme="solarized-dark"] td code
|
[data-theme="solarized-dark"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
border-color: #555;
|
border-color: #555;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
[data-theme="vulcan"] p code,
|
[data-theme="vulcan"] p code.inline,
|
||||||
[data-theme="vulcan"] li code,
|
[data-theme="vulcan"] li code.inline,
|
||||||
[data-theme="vulcan"] td code
|
[data-theme="vulcan"] td code.inline
|
||||||
{
|
{
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
border-color: #555;
|
border-color: #555;
|
||||||
|
|||||||
@@ -23,15 +23,25 @@ class InfoTab extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { autoUpdateEnabled, amaEnabled } = ConfigManager.get()
|
||||||
|
|
||||||
|
this.setState({ config: { autoUpdateEnabled, amaEnabled } })
|
||||||
|
}
|
||||||
|
|
||||||
handleLinkClick(e) {
|
handleLinkClick(e) {
|
||||||
shell.openExternal(e.currentTarget.href)
|
shell.openExternal(e.currentTarget.href)
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleConfigChange(e) {
|
handleConfigChange(e) {
|
||||||
const newConfig = { amaEnabled: this.refs.amaEnabled.checked }
|
const newConfig = {
|
||||||
|
amaEnabled: this.refs.amaEnabled.checked,
|
||||||
|
autoUpdateEnabled: this.refs.autoUpdateEnabled.checked
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ config: newConfig })
|
this.setState({ config: newConfig })
|
||||||
|
return newConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubscriptionFormSubmit(e) {
|
handleSubscriptionFormSubmit(e) {
|
||||||
@@ -77,9 +87,7 @@ class InfoTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSaveButtonClick(e) {
|
handleSaveButtonClick(e) {
|
||||||
const newConfig = {
|
const newConfig = this.state.config
|
||||||
amaEnabled: this.state.config.amaEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newConfig.amaEnabled) {
|
if (!newConfig.amaEnabled) {
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('DISABLE_AMA')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('DISABLE_AMA')
|
||||||
@@ -106,20 +114,17 @@ class InfoTab extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleAutoUpdate() {
|
|
||||||
const newConfig = {
|
|
||||||
autoUpdateEnabled: !this.state.config.autoUpdateEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ config: newConfig })
|
|
||||||
ConfigManager.set(newConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
infoMessage() {
|
infoMessage() {
|
||||||
const { amaMessage } = this.state
|
const { amaMessage } = this.state
|
||||||
return amaMessage ? <p styleName='policy-confirm'>{amaMessage}</p> : null
|
return amaMessage ? <p styleName='policy-confirm'>{amaMessage}</p> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleAutoUpdateChange() {
|
||||||
|
const { autoUpdateEnabled } = this.handleConfigChange()
|
||||||
|
|
||||||
|
ConfigManager.set({ autoUpdateEnabled })
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div styleName='root'>
|
<div styleName='root'>
|
||||||
@@ -260,7 +265,8 @@ class InfoTab extends React.Component {
|
|||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
onChange={this.toggleAutoUpdate.bind(this)}
|
ref='autoUpdateEnabled'
|
||||||
|
onChange={() => this.handleAutoUpdateChange()}
|
||||||
checked={this.state.config.autoUpdateEnabled}
|
checked={this.state.config.autoUpdateEnabled}
|
||||||
/>
|
/>
|
||||||
{i18n.__('Enable Auto Update')}
|
{i18n.__('Enable Auto Update')}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ if (!singleInstance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isUpdateReady = false
|
var isUpdateReady = false
|
||||||
|
let updateFound = false
|
||||||
|
|
||||||
var ghReleasesOpts = {
|
var ghReleasesOpts = {
|
||||||
repo: 'BoostIO/boost-releases',
|
repo: 'BoostIO/boost-releases',
|
||||||
@@ -36,25 +37,33 @@ const updater = new GhReleases(ghReleasesOpts)
|
|||||||
|
|
||||||
// Check for updates
|
// Check for updates
|
||||||
// `status` returns true if there is a new update available
|
// `status` returns true if there is a new update available
|
||||||
function checkUpdate() {
|
function checkUpdate(manualTriggered = false) {
|
||||||
if (!isPackaged) {
|
if (!isPackaged) {
|
||||||
// Prevents app from attempting to update when in dev mode.
|
// Prevents app from attempting to update when in dev mode.
|
||||||
console.log('Updates are disabled in Development mode, see main-app.js')
|
console.log('Updates are disabled in Development mode, see main-app.js')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (!electronConfig.get('autoUpdateEnabled', true)) return
|
|
||||||
if (process.platform === 'linux' || isUpdateReady) {
|
// End if auto updates disabled and it is an automatic check
|
||||||
|
if (!electronConfig.get('autoUpdateEnabled', true) && !manualTriggered) return
|
||||||
|
|
||||||
|
if (process.platform === 'linux' || isUpdateReady || updateFound) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
updater.check((err, status) => {
|
updater.check((err, status) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
var isLatest = err.message === 'There is no newer version.'
|
var isLatest = err.message === 'There is no newer version.'
|
||||||
if (!isLatest) console.error('Updater error! %s', err.message)
|
if (!isLatest) console.error('Updater error! %s', err.message)
|
||||||
|
mainWindow.webContents.send(
|
||||||
|
'update-not-found',
|
||||||
|
isLatest ? 'There is no newer version.' : 'Updater error'
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (status) {
|
if (status) {
|
||||||
mainWindow.webContents.send('update-found', 'Update available!')
|
mainWindow.webContents.send('update-found', 'Update available!')
|
||||||
updater.download()
|
updateFound = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -63,6 +72,7 @@ updater.on('update-downloaded', info => {
|
|||||||
if (mainWindow != null) {
|
if (mainWindow != null) {
|
||||||
mainWindow.webContents.send('update-ready', 'Update available!')
|
mainWindow.webContents.send('update-ready', 'Update available!')
|
||||||
isUpdateReady = true
|
isUpdateReady = true
|
||||||
|
updateFound = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -77,6 +87,14 @@ ipc.on('update-app-confirm', function(event, msg) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipc.on('update-cancel', () => {
|
||||||
|
updateFound = false
|
||||||
|
})
|
||||||
|
|
||||||
|
ipc.on('update-download-confirm', () => {
|
||||||
|
updater.download()
|
||||||
|
})
|
||||||
|
|
||||||
app.on('window-all-closed', function() {
|
app.on('window-all-closed', function() {
|
||||||
app.quit()
|
app.quit()
|
||||||
})
|
})
|
||||||
@@ -113,7 +131,7 @@ app.on('ready', function() {
|
|||||||
if (isUpdateReady) {
|
if (isUpdateReady) {
|
||||||
mainWindow.webContents.send('update-ready', 'Update available!')
|
mainWindow.webContents.send('update-ready', 'Update available!')
|
||||||
} else {
|
} else {
|
||||||
checkUpdate()
|
checkUpdate(msg === 'manual')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, 10 * 1000)
|
}, 10 * 1000)
|
||||||
|
|||||||
@@ -178,6 +178,18 @@ const file = {
|
|||||||
mainWindow.webContents.send('list:isMarkdownNote', 'print')
|
mainWindow.webContents.send('list:isMarkdownNote', 'print')
|
||||||
mainWindow.webContents.send('print')
|
mainWindow.webContents.send('print')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Update',
|
||||||
|
click() {
|
||||||
|
mainWindow.webContents.send('update')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
62
readme.md
62
readme.md
@@ -1,12 +1,26 @@
|
|||||||
> [We've launched desktop and mobile app of the new Boost Note now.](https://github.com/BoostIO/BoostNote.next)
|
> # New Boost Note app is available!
|
||||||
|
|
||||||
> ### [Boost Note for Teams](https://boosthub.io/)
|
|
||||||
>
|
>
|
||||||
> We've developed a collaborative workspace app called "Boost Hub" for developer teams.
|
> We've launched a new Boost Note app which supports real-time collaborative writing.
|
||||||
>
|
>
|
||||||
> It's customizable and easy to optimize for your team like rego blocks and even lets you edit documents together in real-time!
|
> And it is open sourced too! Please check it out! https://github.com/BoostIO/BoostNote-App
|
||||||
|
>
|
||||||
|
> ## 📦 Download App
|
||||||
|
>
|
||||||
|
> ### 🖥 Desktop
|
||||||
|
>
|
||||||
|
> - [🌎 Web App (boostnote.io)](https://boostnote.io)
|
||||||
|
> - [🍎 macOS (.dmg)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-mac.dmg)
|
||||||
|
> - [:framed_picture: Windows (.exe NSIS)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-win.exe)
|
||||||
|
> - [🐧 Linux (.deb)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-linux.deb)
|
||||||
|
> - [🐧 Linux (.rpm)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-linux.rpm)
|
||||||
|
>
|
||||||
|
> ### 📱 Mobile
|
||||||
|
>
|
||||||
|
> - [🌎 Mobile Web App (m.boostnote.io)](https://m.boostnote.io)
|
||||||
|
> - [🍏 iOS (Apple App Store)](https://apps.apple.com/gb/app/boost-note-mobile/id1576176505)
|
||||||
|
> - [🤖 Android (Google Play Store)](https://play.google.com/store/apps/details?id=com.boostio.boostnote2021)
|
||||||
|
|
||||||

|
<h1 align="center">BoostNote-Legacy</h1>
|
||||||
|
|
||||||
<h4 align="center">Note-taking app for programmers. </h4>
|
<h4 align="center">Note-taking app for programmers. </h4>
|
||||||
<h5 align="center">Apps available for Mac, Windows and Linux.</h5>
|
<h5 align="center">Apps available for Mac, Windows and Linux.</h5>
|
||||||
@@ -21,42 +35,6 @@
|
|||||||
|
|
||||||
[Find the latest release of Boostnote here!](https://github.com/BoostIO/boost-releases/releases/)
|
[Find the latest release of Boostnote here!](https://github.com/BoostIO/boost-releases/releases/)
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
[Boost Note Roadmap 2020](https://medium.com/boostnote/boost-note-roadmap-2020-9f06a642f5f1)
|
|
||||||
|
|
||||||
## Authors & Maintainers
|
|
||||||
|
|
||||||
- [Rokt33r](https://github.com/rokt33r)
|
|
||||||
- [KZ](https://github.com/kazup01)
|
|
||||||
- [ZeroX-DG](https://github.com/ZeroX-DG)
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
Thank you to all the people who have contributed to Boostnote!
|
|
||||||
|
|
||||||
<a href="https://github.com/BoostIO/Boostnote/graphs/contributors"><img src="https://opencollective.com/boostnoteio/contributors.svg?width=890" /></a>
|
|
||||||
|
|
||||||
## Supporting Boostnote
|
|
||||||
|
|
||||||
Boostnote is an open source project. It's an independent project with its ongoing development made possible thanks to the support by our amazing backers.
|
|
||||||
|
|
||||||
Issues on Boostnote can be funded by anyone and the money will be distributed to contributors and maintainers. If you use Boostnote please consider becoming a backer:
|
|
||||||
|
|
||||||
[](https://issuehunt.io/repos/53266139)
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
- [Facebook Group](https://www.facebook.com/groups/boostnote/)
|
|
||||||
- [Twitter](https://twitter.com/boostnoteapp)
|
|
||||||
- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/zt-cun7pas3-WwkaezxHBB1lCbUHrwQLXw)
|
|
||||||
- [Blog](https://medium.com/boostnote)
|
|
||||||
- [Reddit](https://www.reddit.com/r/Boostnote/)
|
|
||||||
|
|
||||||
### Boostnote mobile
|
|
||||||
A community project developing a mobile cross-platform version of boostnote for iOS and Android can be found here: [NoteApp](https://github.com/T0M0F/NoteApp)
|
|
||||||
|
|
||||||
|
|
||||||
#### More Information
|
#### More Information
|
||||||
|
|
||||||
- Website: https://boostnote.io
|
- Website: https://boostnote.io
|
||||||
|
|||||||
Reference in New Issue
Block a user