Skip to content

Commit

Permalink
feat(publish): Publishing now updates opened tabs if exist
Browse files Browse the repository at this point in the history
Publishing novels via posting an external message now updates an existing form in opened tabs. It
asks whether to overwrite existing values if they are changed since last publishing.
  • Loading branch information
io-monad committed May 2, 2016
1 parent bf7c291 commit f480a35
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 81 deletions.
3 changes: 3 additions & 0 deletions app/_locales/ja/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
"wentWrong": {
"message": "申し訳ございません。問題が発生しました。"
},
"confirmPublishOverwrite": {
"message": "小説の入力内容が変更されています。\n上書きしてもよろしいですか?"
},

"options": {
"message": "設定"
Expand Down
50 changes: 32 additions & 18 deletions app/scripts/lib/sites/kakuyomu/publish.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import _ from "lodash";
import { translate } from "@io-monad/chrome-util";
import moment from "../../util/moment";
import openPage from "../../util/open-page";
import KakuyomuURL from "./url";
Expand All @@ -12,7 +13,7 @@ import KakuyomuURL from "./url";
export default function publish(publication) {
const url = getURL(publication);
const code = getCode(publication);
return openPage(url, code);
return openPage(url, code, { update: true });
}

function getURL(pub) {
Expand All @@ -24,31 +25,44 @@ function getURL(pub) {
}

function getCode(pub) {
const title = JSON.stringify(pub.title || "");
const body = JSON.stringify(pub.body || "");
let code = `
const embedPub = {
title: pub.title || "",
body: pub.body || "",
};
if (pub.time) {
const time = moment(pub.time).tz("Asia/Tokyo");
embedPub.date = time.format("YYYY-MM-DD");
embedPub.time = time.format("HH:mm");
}
return `
var pub = ${JSON.stringify(embedPub)};
var form = document.getElementById("episode-editForm");
var lastPub = window.novelousLastPublication || { title: "", body: "" };
if (form.title.value !== lastPub.title || form.body.value !== lastPub.body) {
if (!confirm(${JSON.stringify(translate("confirmPublishOverwrite"))})) {
return;
}
}
var change = document.createEvent("HTMLEvents");
change.initEvent("change", true, true);
form.title.value = ${title};
form.title.value = pub.title;
form.title.dispatchEvent(change);
form.body.value = ${body};
form.body.value = pub.body;
form.body.dispatchEvent(change);
`;
if (pub.time) {
const time = moment(pub.time).tz("Asia/Tokyo");
const dateValue = JSON.stringify(time.format("YYYY-MM-DD"));
const timeValue = JSON.stringify(time.format("HH:mm"));
code += `
document.querySelector(".js-reservation-panel-button").click();
if (pub.date && pub.time) {
var button = document.querySelector(".js-reservation-panel-button");
if (!/isPanelShown/.test(button.className)) {
button.click();
}
document.getElementById("reservationInput-reserved").click();
form.reservation_date.value = ${dateValue};
form.reservation_time.value = ${timeValue};
`;
}
form.reservation_date.value = pub.date;
form.reservation_time.value = pub.time;
}
return code;
window.novelousLastPublication = pub;
`;
}
48 changes: 30 additions & 18 deletions app/scripts/lib/sites/narou/publish.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import _ from "lodash";
import { translate } from "@io-monad/chrome-util";
import moment from "../../util/moment";
import openPage from "../../util/open-page";
import NarouURL from "./url";
Expand All @@ -12,7 +13,7 @@ import NarouURL from "./url";
export default function publish(publication) {
const url = getURL(publication);
const code = getCode(publication);
return openPage(url, code);
return openPage(url, code, { update: true });
}

function getURL(pub) {
Expand All @@ -24,25 +25,36 @@ function getURL(pub) {
}

function getCode(pub) {
const title = JSON.stringify(pub.title || "");
const body = JSON.stringify(pub.body || "");
let code = `
var form = document.getElementById("manage_form");
form.subtitle.value = ${title};
form.novel.value = ${body};
`;

const embedPub = {
title: pub.title || "",
body: pub.body || "",
};
if (pub.time) {
const time = moment(pub.time).tz("Asia/Tokyo");
const monthValue = JSON.stringify(time.format("YYYY-MM"));
const dayValue = JSON.stringify(time.format("D"));
const hourValue = JSON.stringify(time.format("H"));
code += `
form.month.value = ${monthValue};
form.day.value = ${dayValue};
form.hour.value = ${hourValue};
`;
embedPub.month = time.format("YYYY-MM");
embedPub.day = time.format("D");
embedPub.hour = time.format("H");
}
return `
var pub = ${JSON.stringify(embedPub)};
var form = document.getElementById("manage_form");
return code;
var lastPub = window.novelousLastPublication || { title: "", body: "" };
if (form.subtitle.value !== lastPub.title || form.novel.value !== lastPub.body) {
if (!confirm(${JSON.stringify(translate("confirmPublishOverwrite"))})) {
return;
}
}
form.subtitle.value = pub.title;
form.novel.value = pub.body;
if (pub.month && pub.day) {
form.month.value = pub.month;
form.day.value = pub.day;
form.hour.value = pub.hour;
}
window.novelousLastPublication = pub;
`;
}
49 changes: 39 additions & 10 deletions app/scripts/lib/util/open-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,49 @@
*
* @param {string} url - A URL of the opening page.
* @param {string} code - A code to be executed on the page.
* @param {Object} [options] - Options.
* @param {boolean} [options.update=false] - Set this to `true` for updating existing tab.
* @return {Promise}
*/
export default function openPage(url, code) {
return new Promise((resolve, reject) => {
chrome.tabs.create({ url }, (tab) => {
const wrapped = wrapInjectCode(code);
chrome.tabs.executeScript(tab.id, { code: wrapped }, (results) => {
// results = [error] or [null]
if (results.length > 0 && results[0]) {
reject(results[0]);
export default function openPage(url, code, options) {
options = options || {};
return new Promise(resolve => {
if (options.update) {
chrome.tabs.query({ url }, (tabs) => {
if (tabs.length > 0) {
chrome.tabs.update(tabs[0].id, { active: true }, tab => {
resolve(executeCode(tab, code));
});
} else {
resolve();
chrome.tabs.create({ url }, tab => {
resolve(executeCode(tab, code));
});
}
});
} else {
chrome.tabs.create({ url }, tab => {
resolve(executeCode(tab, code));
});
}
});
}

/**
* @param {chrome~Tab} tab
* @param {string} code
* @return {Promise}
* @private
*/
function executeCode(tab, code) {
return new Promise((resolve, reject) => {
const wrapped = wrapInjectCode(code);
chrome.tabs.executeScript(tab.id, { code: wrapped }, (results) => {
// results = [error] or [null]
if (results.length > 0 && results[0]) {
reject(results[0]);
} else {
resolve();
}
});
});
}
Expand All @@ -35,6 +64,6 @@ function wrapInjectCode(code) {
return e.message || e;
}
return null;
})();
}());
`;
}
69 changes: 52 additions & 17 deletions test/lib/sites/kakuyomu/publish-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,69 @@ import { _, assert, factory } from "../../../common";
import publish from "../../../../app/scripts/lib/sites/kakuyomu/publish";

describe("KakuyomuPublish", () => {
it("publishes novel to sites", () => {
const pub = factory.buildSync("publication", {
let pub;
let publishUrl;
before(() => {
pub = factory.buildSync("publication", {
sites: {
kakuyomu: { novelId: "12341234" },
},
});
chrome.tabs.create.callsArgWithAsync(1, { id: 123 });
chrome.tabs.executeScript.callsArgWithAsync(2, [null]);
publishUrl = `https://kakuyomu.jp/my/works/${pub.sites.kakuyomu.novelId}/episodes/new`;
});

it("opens a new tab with publication contents", () => {
chrome.tabs.query.yieldsAsync([]);
chrome.tabs.create.yieldsAsync({ id: 123 });
chrome.tabs.executeScript.yieldsAsync([null]);

return publish(pub).then(() => {
assert(chrome.tabs.create.calledOnce);
assert.deepEqual(chrome.tabs.create.args[0][0], {
url: `https://kakuyomu.jp/my/works/${pub.sites.kakuyomu.novelId}/episodes/new`,
assert(chrome.tabs.query.calledOnce === true);
assert.deepEqual(chrome.tabs.query.args[0][0], { url: publishUrl });

assert(chrome.tabs.create.calledOnce === true);
assert.deepEqual(chrome.tabs.create.args[0][0], { url: publishUrl });

assert(chrome.tabs.executeScript.calledOnce === true);
assert(chrome.tabs.executeScript.args[0][0] === 123);
assert(_.isString(chrome.tabs.executeScript.args[0][1].code));

const code = chrome.tabs.executeScript.args[0][1].code;
const embedPub = JSON.parse(code.match(/var pub = (.+?);/)[1]);
assert.deepEqual(embedPub, {
title: pub.title,
body: pub.body,
date: "2016-03-01",
time: "11:34",
});
assert(chrome.tabs.executeScript.calledOnce);
});
});

it("updates an existing tab with publication contents", () => {
chrome.tabs.query.yieldsAsync([{ id: 123 }]);
chrome.tabs.update.yieldsAsync({ id: 123 });
chrome.tabs.executeScript.yieldsAsync([null]);

return publish(pub).then(() => {
assert(chrome.tabs.query.calledOnce === true);
assert.deepEqual(chrome.tabs.query.args[0][0], { url: publishUrl });

assert(chrome.tabs.update.calledOnce === true);
assert(chrome.tabs.update.args[0][0] === 123);
assert.deepEqual(chrome.tabs.update.args[0][1], { active: true });

assert(chrome.tabs.executeScript.calledOnce === true);
assert(chrome.tabs.executeScript.args[0][0] === 123);
assert(_.isString(chrome.tabs.executeScript.args[0][1].code));

const code = chrome.tabs.executeScript.args[0][1].code;
const formValue = (name) => {
const re = new RegExp(`form\\.${name}\\.value = (.+?);`);
return JSON.parse(code.match(re)[1]);
};

assert(formValue("title") === pub.title);
assert(formValue("body") === pub.body);
assert(formValue("reservation_date") === "2016-03-01");
assert(formValue("reservation_time") === "11:34");
const embedPub = JSON.parse(code.match(/var pub = (.+?);/)[1]);
assert.deepEqual(embedPub, {
title: pub.title,
body: pub.body,
date: "2016-03-01",
time: "11:34",
});
});
});
});
72 changes: 54 additions & 18 deletions test/lib/sites/narou/publish-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,67 @@ import { _, assert, factory } from "../../../common";
import publish from "../../../../app/scripts/lib/sites/narou/publish";

describe("NarouPublish", () => {
it("publishes novel to sites", () => {
const pub = factory.buildSync("publication");
chrome.tabs.create.callsArgWithAsync(1, { id: 123 });
chrome.tabs.executeScript.callsArgWithAsync(2, [null]);
let pub;
let publishUrl;
before(() => {
pub = factory.buildSync("publication");
publishUrl = `http://syosetu.com/usernovelmanage/ziwainput/ncode/${pub.sites.narou.novelId}/`;
});

it("opens a new tab with publication contents", () => {
chrome.tabs.query.yieldsAsync([]);
chrome.tabs.create.yieldsAsync({ id: 123 });
chrome.tabs.executeScript.yieldsAsync([null]);

return publish(pub).then(() => {
assert(chrome.tabs.create.calledOnce);
assert.deepEqual(chrome.tabs.create.args[0][0], {
url: `http://syosetu.com/usernovelmanage/ziwainput/ncode/${pub.sites.narou.novelId}/`,
assert(chrome.tabs.query.calledOnce === true);
assert.deepEqual(chrome.tabs.query.args[0][0], { url: publishUrl });

assert(chrome.tabs.create.calledOnce === true);
assert.deepEqual(chrome.tabs.create.args[0][0], { url: publishUrl });

assert(chrome.tabs.executeScript.calledOnce === true);
assert(chrome.tabs.executeScript.args[0][0] === 123);
assert(_.isString(chrome.tabs.executeScript.args[0][1].code));

const code = chrome.tabs.executeScript.args[0][1].code;
const embedPub = JSON.parse(code.match(/var pub = (.+?);/)[1]);
assert.deepEqual(embedPub, {
title: pub.title,
body: pub.body,
month: "2016-03",
day: "1",
hour: "11",
});
assert(chrome.tabs.executeScript.calledOnce);
});
});

it("updates an existing tab with publication contents", () => {
chrome.tabs.query.yieldsAsync([{ id: 123 }]);
chrome.tabs.update.yieldsAsync({ id: 123 });
chrome.tabs.executeScript.yieldsAsync([null]);

return publish(pub).then(() => {
assert(chrome.tabs.query.calledOnce === true);
assert.deepEqual(chrome.tabs.query.args[0][0], { url: publishUrl });

assert(chrome.tabs.update.calledOnce === true);
assert(chrome.tabs.update.args[0][0] === 123);
assert.deepEqual(chrome.tabs.update.args[0][1], { active: true });

assert(chrome.tabs.executeScript.calledOnce === true);
assert(chrome.tabs.executeScript.args[0][0] === 123);
assert(_.isString(chrome.tabs.executeScript.args[0][1].code));

const code = chrome.tabs.executeScript.args[0][1].code;
const formValue = (name) => {
const re = new RegExp(`form\\.${name}\\.value = (.+?);`);
return JSON.parse(code.match(re)[1]);
};

assert(formValue("subtitle") === pub.title);
assert(formValue("novel") === pub.body);
assert(formValue("month") === "2016-03");
assert(formValue("day") === "1");
assert(formValue("hour") === "11");
const embedPub = JSON.parse(code.match(/var pub = (.+?);/)[1]);
assert.deepEqual(embedPub, {
title: pub.title,
body: pub.body,
month: "2016-03",
day: "1",
hour: "11",
});
});
});
});

0 comments on commit f480a35

Please sign in to comment.