add support for tags

This commit is contained in:
Dima Gerasimov 2019-01-06 20:44:00 +00:00
parent 8f585ebc88
commit de46310d93
9 changed files with 89 additions and 49 deletions

View file

@ -1,39 +1,29 @@
* TODO some sort of append logic? e.g. don't dump immediately and add as subitems?
* ???
npm install --save-dev @babel/core @babel/preset-env
npm install babel-preset-stage-0
npm install babel-preset-env -- wtf is that shit??
npm run build
npm run flow
* DONE [#A] move server to a separate folder, systemd install script
CLOSED: [2019-01-05 Sat 14:38]
* TODO [#B] release somewhere? not sure if necessary
* TODO [#B] docs on using
* START [#A] entering additional information and tags
* TODO [#B] doesn't look like hotkey working unless you manually rebind.. wtf?
* TODO the benefit is that you can also add anything as a backend, e.g. you might be more of markdown fan or todo.txt
* TODO shortcut for org mode to create timestsamped note
* TODO [#C] motivation
** TODO the benefit is that you can also add anything as a backend, e.g. you might be more of markdown fan or todo.txt
* TODO [#C] how to test it? try on different pages?
* TODO [#C] some sort of append logic? e.g. don't dump immediately and add as subitems?
* TODO [#D] do not minfy for dev
* TODO not sure, maybe extension press should be default? control it via option?
* TODO or, add menu to extension?
* TODO [#B] release somewhere? not sure if necessary
* TODO unsafe-eval in content security policy??
* TODO make manifest templated so we don't have to hardcode actions
* TODO [#B] docs on using
* DONE [#A] move server to a separate folder, systemd install script
CLOSED: [2019-01-05 Sat 14:38]
* DONE [#A] entering additional information and tags
CLOSED: [2019-01-06 Sun 20:41]
* DONE [#B] circleci?
CLOSED: [2019-01-06 Sun 13:50]
* DONE [#D] nicer manifest?
CLOSED: [2019-01-06 Sun 13:43]
* TODO [#D] do not minfy for dev
* TODO [#C] motivation
* TODO [#B] doesn't look like hotkey working unless you manually rebind.. wtf?
* TODO [#C] how to test it? try on different pages?

View file

@ -1,6 +1,6 @@
{
"name": "grasp-extension",
"version": "0.2.0",
"version": "0.3.0",
"description": "A reliable way of capturing web pages and content",
"scripts": {
"build": "webpack --progress --profile --colors",

View file

@ -1,5 +1,6 @@
"""First API, local access only"""
import json
import re
import hug # type: ignore
import hug.types as T # type: ignore
@ -23,11 +24,16 @@ def capture(
title: T.Nullable(T.text),
selection: T.Nullable(T.text),
comment: T.Nullable(T.text),
tag_str: T.Nullable(T.text),
):
log("capturing", url, title, selection, comment)
heading = url
parts = []
tags = []
if not empty(tag_str):
tags = re.split('[\s,]', tag_str)
tags = [t for t in tags if not empty(t)] # just in case
if not empty(title):
heading = title
@ -55,7 +61,7 @@ def capture(
CAPTURE_PATH,
heading=heading,
body=body,
tags=['grasp'],
tags=tags,
todo=False,
)
response.update({

View file

@ -2,14 +2,14 @@
// TODO do I really need to annotate all files with @flow??
import {COMMAND_CAPTURE_SIMPLE, METHOD_CAPTURE_WITH_EXTRAS, showNotification} from './common';
import {capture_url} from './config';
import {defaultTagStr, capture_url} from './options';
type Params = {
url: string,
title: ?string,
selection: ?string,
comment: ?string,
tag_str: ?string,
}
@ -19,7 +19,6 @@ function makeCaptureRequest(
const data = JSON.stringify(params);
console.log(`[background] capturing ${data}`);
var request = new XMLHttpRequest();
request.open('POST', capture_url(), true);
request.onreadystatechange = () => {
@ -51,13 +50,17 @@ function makeCaptureRequest(
request.send(data);
}
function capture(comment: ?string = null) {
function capture(comment: ?string = null, tag_str: ?string = null) {
chrome.tabs.query({currentWindow: true, active: true }, tabs => {
const tab = tabs[0];
if (tab.url == null) {
showNotification('ERROR: trying to capture null');
return;
}
if (tag_str === null) {
tag_str = defaultTagStr();
}
const url: string = tab.url;
const title: ?string = tab.title;
@ -72,6 +75,7 @@ function capture(comment: ?string = null) {
title: title,
selection: selection,
comment: comment,
tag_str: tag_str,
});
});
});
@ -80,14 +84,15 @@ function capture(comment: ?string = null) {
chrome.commands.onCommand.addListener(command => {
if (command === COMMAND_CAPTURE_SIMPLE) {
capture(null);
capture(null, null);
}
});
chrome.runtime.onMessage.addListener((message: any, sender: chrome$MessageSender, sendResponse) => {
if (message.method === METHOD_CAPTURE_WITH_EXTRAS) {
const comment = message.comment;
capture(comment);
const tag_str = message.tag_str;
capture(comment, tag_str);
}
});

View file

@ -1,9 +0,0 @@
/* @flow */
// TODO configure port in options?
const capture_endpoint = 'capture';
const port = 8090;
export function capture_url (): string {
return `http://localhost:${port}/${capture_endpoint}`;
}

View file

@ -0,0 +1,16 @@
/* @flow */
const capture_endpoint = 'capture';
function port(): string {
return "8090";
}
// none means do not use tags
export function defaultTagStr (): ?string {
return 'grasp';
}
export function capture_url (): string {
return `http://localhost:${port()}/${capture_endpoint}`;
}

View file

@ -5,12 +5,18 @@ import {METHOD_CAPTURE_WITH_EXTRAS} from './common';
// TODO template it in html too?
const BUTTON_ID = 'button_id';
const COMMENT_ID = 'comment_id';
const TAGS_ID = 'tags_id';
function getComment(): HTMLInputElement {
const comment = ((document.getElementById(COMMENT_ID) : any): HTMLInputElement);
return comment;
}
function getTags(): HTMLInputElement {
const tags = ((document.getElementById(TAGS_ID) : any): HTMLInputElement);
return tags;
}
function getButton(): HTMLElement {
const button = ((document.getElementById(BUTTON_ID): any): HTMLElement);
return button;
@ -18,25 +24,48 @@ function getButton(): HTMLElement {
function submitComment () {
const comment_text = getComment().value;
const tag_str = getTags().value;
// TODO focus
chrome.runtime.sendMessage({
'method': METHOD_CAPTURE_WITH_EXTRAS,
'comment': comment_text,
'tag_str': tag_str,
}, resp => {
console.log("[popup] captured!");
});
window.close();
}
// $FlowFixMe
function ctrlEnterSubmit(e) {
if (e.ctrlKey && e.key === 'Enter') {
submitComment();
}
}
// https://stackoverflow.com/a/6003829/706389
function moveCaretToEnd(el) {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
el.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}
function setupPage () {
const comment = getComment();
comment.focus();
// $FlowFixMe
comment.addEventListener('keydown', e => {
if (e.ctrlKey && e.key === 'Enter') {
submitComment();
}
});
comment.addEventListener('keydown', ctrlEnterSubmit);
const tags = getTags();
tags.addEventListener('keydown', ctrlEnterSubmit);
tags.addEventListener('focus', () => moveCaretToEnd(tags)); // to put cursor to the end of tags when tabbed
getButton().addEventListener('click', submitComment);
}

View file

@ -4,7 +4,10 @@
<meta charset="UTF-8">
</head>
<body>
<!-- TODO ugh didn't work -->
<!-- <%= htmlWebpackPlugin.options.ids.tags %> -->
<div><textarea id="comment_id" rows="4" cols="50" placeholder="Enter your comments; press Ctrl-Enter to capture"></textarea></div>
<div><button id="button_id" type="button" align="right">capture!</button></div>
<div><textarea id="tags_id" rows="1" cols="50">grasp</textarea></div>
<div><button id="button_id" type="button" align="right">capture!</button></div>
</body>
</html>

View file

@ -81,7 +81,7 @@ var options = {
new HtmlWebpackPlugin({
template: path.join(__dirname, "src", "popup.html"),
filename: "popup.html",
chunks: ["popup"]
chunks: ["popup"],
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, "src", "options.html"),