Commit f5a2fbb8 authored by Laurent Wouters's avatar Laurent Wouters
Browse files

[fix] Refactoring the popup UI

parent 1b789a21b18e
......@@ -34,7 +34,8 @@ import {
ORIGIN_KIND_DIRECT,
ORIGIN_KIND_LINKED_HTML,
ORIGIN_KIND_NEGOTIATED,
ORIGIN_KIND_REDIRECTED
ORIGIN_KIND_REDIRECTED,
DocumentStatus
} from "../common/data";
import { Message, activateNegotiated } from "../common/messages";
/// <reference path="./fallback.d.ts"/>
......@@ -71,17 +72,19 @@ reloadRegistryFromStorage(registry)
*/
function onObservedTabUpdated(tabId: number): void {
let observation = resolveObservationsForTab(allObservations, tabId);
if (hasDetectedData(observation)) {
if (observation.preemptable) {
chrome.pageAction.setPopup({
tabId: tabId,
popup: chrome.extension.getURL("popup/index.html")
});
}
let isLit =
observation.status != DocumentStatus.off || hasDetectedData(observation);
let hasPopup = observation.status == DocumentStatus.active;
if (isLit) {
chrome.pageAction.show(tabId);
} else {
chrome.pageAction.hide(tabId);
}
chrome.pageAction.setPopup({
tabId: tabId,
popup: hasPopup ? chrome.extension.getURL("popup/index.html") : ""
});
}
/**
......@@ -136,17 +139,22 @@ function onSendingHeaders(
return {};
let observation = allObservations[details.tabId];
if (observation == null || observation == undefined) return {};
// do not request RDF for off and asleep tabs
if (
observation.origin == null ||
observation.origin.kind != ORIGIN_KIND_REDIRECTED
observation.status == DocumentStatus.off ||
observation.status == DocumentStatus.asleep
)
return {};
if (observation.origin && observation.origin.kind == ORIGIN_KIND_REDIRECTED) {
observation.origin.kind = ORIGIN_KIND_NEGOTIATED;
} else {
observation.origin = {
kind: ORIGIN_KIND_DIRECT,
url: details.url
};
if (observation.origin.kind == ORIGIN_KIND_REDIRECTED) {
observation.origin.kind = ORIGIN_KIND_NEGOTIATED;
}
if (observation.preemptable) {
// this tab has been preempted
let headers = details.requestHeaders;
......@@ -354,7 +362,7 @@ chrome.runtime.onMessage.addListener(
sendResponse({ ok: null, error: reason });
});
return true;
} else if (request.requestType == "TurnOffTab") {
} else if (request.requestType == "TurnOffForTab") {
let tabId = request.payload;
if (tabId == null || tabId == undefined) {
// deduce from the sender
......@@ -362,9 +370,19 @@ chrome.runtime.onMessage.addListener(
}
let observation = allObservations[tabId];
if (observation == undefined) sendResponse(null);
observation.negotiated = null;
observation.preemptable = false;
chrome.pageAction.hide(tabId);
observation.status = DocumentStatus.asleep;
onObservedTabUpdated(tabId);
sendResponse(observation);
} else if (request.requestType == "ToggleRawForTab") {
let tabId = request.payload;
if (tabId == null || tabId == undefined) {
// deduce from the sender
tabId = sender.tab.id;
}
let observation = allObservations[tabId];
if (observation == undefined) sendResponse(null);
observation.status = DocumentStatus.activeRaw;
onObservedTabUpdated(tabId);
sendResponse(observation);
}
}
......@@ -372,39 +390,21 @@ chrome.runtime.onMessage.addListener(
chrome.pageAction.onClicked.addListener((tab: chrome.tabs.Tab) => {
let observation = resolveObservationsForTab(allObservations, tab.id);
if (observation.negotiated != null && observation.negotiated != undefined) {
// a dataset can be obtained through HTTP content negotiation
// => open a new tab with the same observations
let callback = (openedTab: chrome.tabs.Tab) => {
allObservations[openedTab.id] = JSON.parse(JSON.stringify(observation));
chrome.pageAction.setPopup({
tabId: openedTab.id,
popup: chrome.extension.getURL("popup/index.html")
});
activateNegotiated(openedTab.id, observation);
};
let promise: any = chrome.tabs.create(
{
windowId: tab.windowId,
index: tab.index + 1,
url: observation.url,
active: true,
openerTabId: tab.id
},
callback
);
if (promise != undefined && promise != null) {
promise.then(callback);
}
} else {
// dataset is obtained from another source
// => open the linked-data browser as an extension page
let url = chrome.extension.getURL(
"ldbrowser/index.html?target=" + encodeURIComponent(observation.url)
);
if (observation.status == DocumentStatus.off) {
// this tab was off
let isNegotiated =
observation.negotiated != null && observation.negotiated != undefined;
let callback = (openedTab: chrome.tabs.Tab) => {
allObservations[openedTab.id] = JSON.parse(JSON.stringify(observation));
allObservations[openedTab.id].status = DocumentStatus.active;
onObservedTabUpdated(openedTab.id);
if (isNegotiated) activateNegotiated(openedTab.id, observation);
};
let url = isNegotiated
? observation.url
: chrome.extension.getURL(
"ldbrowser/index.html?target=" + encodeURIComponent(observation.url)
);
let promise: any = chrome.tabs.create(
{
windowId: tab.windowId,
......@@ -418,5 +418,12 @@ chrome.pageAction.onClicked.addListener((tab: chrome.tabs.Tab) => {
if (promise != undefined && promise != null) {
promise.then(callback);
}
} else if (
observation.status == DocumentStatus.asleep ||
observation.status == DocumentStatus.activeRaw
) {
observation.status = DocumentStatus.active;
onObservedTabUpdated(tab.id);
chrome.tabs.reload(tab.id);
}
});
......@@ -31,6 +31,7 @@ export interface CurrentTabConfigProps {
onClickSeeResources: () => void;
onClickGotoOptions: () => void;
onClickTurnOff: () => void;
onClickDisplayRaw: () => void;
onTabCommandAutomatic: (event: React.FormEvent<HTMLInputElement>) => void;
onTabCommandClearTopic: () => void;
onTabCommandSelectView: (event: React.FormEvent<HTMLSelectElement>) => void;
......@@ -88,15 +89,14 @@ export class CurrentTabConfig extends React.Component<
</span>
</a>
</div>
<div className="col-2" />
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onClickTurnOff}
title="Turn off on this tab"
onClick={this.props.onClickDisplayRaw}
title="Display the raw source for this document"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/off.svg" />
<img width="24px" src="../icons/raw.svg" />
</span>
</a>
</div>
......@@ -111,6 +111,17 @@ export class CurrentTabConfig extends React.Component<
</span>
</a>
</div>
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onClickTurnOff}
title="Turn off on this tab"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/off.svg" />
</span>
</a>
</div>
</div>
<div className="row">
<div className="col-12">
......
......@@ -584,6 +584,28 @@ function compareSources(x: DocumentSource, y: DocumentSource): number {
*/
export const NO_DATA = new DocumentSourceNone();
/**
* Describes the status of a document (on a tab)
*/
export enum DocumentStatus {
/**
* The extension shall remain inactive on this tab (default)
*/
off,
/**
* The extension is activated on this tab
*/
active,
/**
* The extension is activated on this tab, displaying in raw mode
*/
activeRaw,
/**
* The extension has previously been acticated on this tab but shall remain asleep for the time being
*/
asleep
}
/**
* The observations made for a specific document
*/
......@@ -596,6 +618,7 @@ export class DocumentObservations {
this.preemptable = false;
this.negotiated = null;
this.totalLoaded = 0;
this.status = DocumentStatus.off;
}
/**
* The origin of this document
......@@ -625,6 +648,10 @@ export class DocumentObservations {
* The total number of statements loaded from this document
*/
totalLoaded: number;
/**
* The requested status for this document
*/
status: DocumentStatus;
}
/**
......@@ -662,7 +689,8 @@ export function observeContent(
sources: [source],
preemptable: true,
negotiated: null,
totalLoaded: 0
totalLoaded: 0,
status: DocumentStatus.off
};
return observations;
} else {
......@@ -699,7 +727,8 @@ export function observeContent(
sources: sources,
preemptable: MIME.hasOwnProperty(observable.contentType),
negotiated: negotiated != undefined ? negotiated : null,
totalLoaded: 0
totalLoaded: 0,
status: DocumentStatus.off
};
return observations;
}
......
......@@ -242,7 +242,36 @@ export function backgroundTurnOffForTab(
) => {
chrome.runtime.sendMessage(
{
requestType: "TurnOffTab",
requestType: "TurnOffForTab",
payload: tabId
},
(result: DocumentObservations) => {
if (result == null) {
reject("Invalid tab");
} else {
resolve(result);
}
}
);
}
);
}
/**
* Sends to the background a message to request the tab to display raw content
* @param id The identifier of a tab
*/
export function backgroundToggleRawForTab(
tabId: number
): Promise<DocumentObservations> {
return new Promise<DocumentObservations>(
(
resolve: (result: DocumentObservations) => void,
reject: (reason: any) => void
) => {
chrome.runtime.sendMessage(
{
requestType: "ToggleRawForTab",
payload: tabId
},
(result: DocumentObservations) => {
......@@ -268,6 +297,17 @@ export function turnOffTab(tabId: number): void {
});
}
/**
* Sends to a tab a message to display raw content
* @param id The identifier of a tab
*/
export function tabDisplayRaw(tabId: number): void {
chrome.tabs.sendMessage(tabId, {
requestType: "DisplayRaw",
payload: tabId
});
}
/**
* Gets the data for the current resource
* @param id The identifier of a tab
......
......@@ -22,9 +22,14 @@ import "chrome";
import {
Message,
getObservationsFor,
backgroundTurnOffForTab
backgroundTurnOffForTab,
backgroundToggleRawForTab
} from "../common/messages";
import { DocumentObservations, findLinksInDocument } from "../common/data";
import {
DocumentObservations,
findLinksInDocument,
DocumentStatus
} from "../common/data";
import { Viewer, newViewer } from "../common/viewer";
import { LDBrowser, newBrowser } from "../common/browser";
require("../common/view-defaults-impl");
......@@ -70,6 +75,14 @@ function initializeBrowser(): LDBrowser {
.catch((reason: any) => {
console.log(reason);
});
} else if (request.requestType == "DisplayRaw") {
backgroundToggleRawForTab(request.payload)
.then((value: any) => {
window.location.reload(true);
})
.catch((reason: any) => {
console.log(reason);
});
} else if (request.requestType == "GetCurrentResource") {
sendResponse(browser.getCurrentResource());
} else if (request.requestType == "UpdateCurrentCommand") {
......@@ -107,6 +120,13 @@ function main() {
// Gets data about this tab from the background and reply with the HTML head data
getObservationsFor(null).then((observation: DocumentObservations) => {
sendHead(observation);
if (
observation.status == DocumentStatus.off ||
observation.status == DocumentStatus.asleep ||
observation.status == DocumentStatus.activeRaw
)
return;
if (observation.preemptable) {
let browser = initializeBrowser();
browser.onReachedUri(window.location.href, observation.origin);
......
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 502.664 502.664" style="enable-background:new 0 0 502.664 502.664;" xml:space="preserve">
<g>
<g>
<path style="fill:#010002;" d="M153.821,358.226L0,274.337v-46.463l153.821-83.414v54.574L46.636,250.523l107.185,53.431
C153.821,303.954,153.821,358.226,153.821,358.226z"/>
<path style="fill:#010002;" d="M180.094,387.584L282.103,115.08h32.227L212.084,387.584H180.094z"/>
<path style="fill:#010002;" d="M348.843,358.226v-54.272l107.164-52.999l-107.164-52.59v-53.927l153.821,83.522v46.183
L348.843,358.226z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
......@@ -25,7 +25,8 @@ import {
getViewRegistry,
getCurrentResource,
updateCurrentCommand,
turnOffTab
turnOffTab,
tabDisplayRaw
} from "../common/messages";
import { ResourceData } from "../common/data";
import * as LANGUAGES from "../common/data.iso639.json";
......@@ -72,6 +73,7 @@ class Popup extends React.Component<{}, State> {
};
this.onOpenOptions = this.onOpenOptions.bind(this);
this.onTunOff = this.onTunOff.bind(this);
this.onDisplayRaw = this.onDisplayRaw.bind(this);
this.onUpdateTabCommand = this.onUpdateTabCommand.bind(this);
this.onTabCommandAutomatic = this.onTabCommandAutomatic.bind(this);
this.onTabCommandClearTopic = this.onTabCommandClearTopic.bind(this);
......@@ -101,6 +103,10 @@ class Popup extends React.Component<{}, State> {
turnOffTab(this.state.tabId);
}
onDisplayRaw() {
tabDisplayRaw(this.state.tabId);
}
onUpdateTabCommand() {
updateCurrentCommand(this.state.tabId, this.state.data.command).then(
(data: ResourceData) => {
......@@ -163,6 +169,7 @@ class Popup extends React.Component<{}, State> {
}}
onClickGotoOptions={this.onOpenOptions}
onClickTurnOff={this.onTunOff}
onClickDisplayRaw={this.onDisplayRaw}
onTabCommandAutomatic={this.onTabCommandAutomatic}
onTabCommandSelectView={this.onTabCommandSelectView}
onTabCommandSelectLanguage={this.onTabCommandSelectLanguage}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment