Skip to content

Commit b218d4b

Browse files
committed
Bug 1782578 - Build out the text recognition modal r=nordzilla,fluent-reviewers,Jamie,flod
This patch contains the bulk of the implementation of the modal. Most of it is UI work and wiring together the various components. There is a bit of complexity in the clustering algorithm, as I implemented the DBSCAN algorithm to help cluster the text recognition results. I filed Bug 1782586 to improve the DBSCAN algorithm, but currently it works the same as the algorithm is described on Wikipedia. Note that the tests are in the following patch in order to keep the line count small for this patch. Differential Revision: https://phabricator.services.mozilla.com/D153396
1 parent 0a77c03 commit b218d4b

File tree

7 files changed

+557
-4
lines changed

7 files changed

+557
-4
lines changed

browser/actors/ContextMenuChild.jsm

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,11 @@ class ContextMenuChild extends JSWindowActorChild {
167167
let img = lazy.ContentDOMReference.resolve(
168168
message.data.targetIdentifier
169169
);
170-
img.recognizeCurrentImageText();
171-
break;
170+
const { direction } = this.contentWindow.getComputedStyle(img);
171+
172+
return img.recognizeCurrentImageText().then(results => {
173+
return { results, direction };
174+
});
172175
}
173176

174177
case "ContextMenu:ToggleRevealPassword": {

browser/actors/ContextMenuParent.jsm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ContextMenuParent extends JSWindowActorParent {
4040
}
4141

4242
getImageText(targetIdentifier) {
43-
this.sendAsyncMessage("ContextMenu:GetImageText", {
43+
return this.sendQuery("ContextMenu:GetImageText", {
4444
targetIdentifier,
4545
});
4646
}

browser/base/content/nsContextMenu.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2301,7 +2301,18 @@ class nsContextMenu {
23012301
}
23022302

23032303
getImageText() {
2304-
this.actor.getImageText(this.targetIdentifier);
2304+
let dialogBox = gBrowser.getTabDialogBox(this.browser);
2305+
const imageTextResult = this.actor.getImageText(this.targetIdentifier);
2306+
const { dialog } = dialogBox.open(
2307+
"chrome://browser/content/textrecognition/textrecognition.html",
2308+
{
2309+
features: "resizable=no",
2310+
modalType: Services.prompt.MODAL_TYPE_CONTENT,
2311+
},
2312+
imageTextResult,
2313+
() => dialog.resizeVertically(),
2314+
openLinkIn
2315+
);
23052316
}
23062317

23072318
drmLearnMore(aEvent) {
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,119 @@
11
/* This Source Code Form is subject to the terms of the Mozilla Public
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
6+
.textRecognitionText {
7+
overflow-y: auto;
8+
max-height: 300px;
9+
flex: 1;
10+
display: none;
11+
}
12+
13+
.textRecognitionText p:first-child {
14+
margin-top: 0;
15+
}
16+
17+
.textRecognitionText p:last-child {
18+
margin-bottom: 0;
19+
}
20+
21+
.textRecognition {
22+
--gap: 16px;
23+
display: flex;
24+
flex-direction: column;
25+
background-color: var(--in-content-page-background);
26+
width: 412px;
27+
gap: var(--gap);
28+
padding: var(--gap);
29+
}
30+
31+
.textRecognitionHeader {
32+
font-weight: bold;
33+
display: flex;
34+
flex-direction: row;
35+
align-items: center;
36+
}
37+
38+
.textRecognitionFooter {
39+
text-align: end;
40+
}
41+
42+
.textRecognitionThrobber {
43+
display: inline-block;
44+
width: 16px;
45+
height: 16px;
46+
position: relative;
47+
overflow: hidden;
48+
margin-inline-end: 5.5px;
49+
}
50+
51+
.textRecognitionThrobber::before {
52+
content: "";
53+
position: absolute;
54+
background-image: url("chrome://browser/skin/tabbrowser/loading.svg");
55+
background-position: left center;
56+
background-repeat: no-repeat;
57+
width: 480px;
58+
height: 100%;
59+
animation: throbber-animation-ltr 1.05s steps(30) infinite;
60+
-moz-context-properties: fill;
61+
fill: currentColor;
62+
opacity: 0.7;
63+
}
64+
65+
.textRecognitionThrobber:dir(rtl)::before {
66+
background-position-x: right;
67+
animation: throbber-animation-rtl 1.05s steps(30) infinite;
68+
}
69+
70+
.textRecognitionSuccessIcon {
71+
display: inline-block;
72+
background-color: #2AC3A2;
73+
border: 3px solid #2AC3A2;
74+
fill: --in-content-page-background;
75+
-moz-context-properties: fill;
76+
border-radius: 10px;
77+
width: 12px;
78+
height: 12px;
79+
margin-inline-end: 6px;
80+
animation: success-animation 0.3s cubic-bezier(.3,2,.48,.94);
81+
}
82+
83+
.textRecognitionNoResultIcon {
84+
display: inline-block;
85+
fill: #FFBF00;
86+
-moz-context-properties: fill;
87+
width: 18px;
88+
height: 18px;
89+
margin-inline-end: 8px;
90+
}
91+
92+
@media (prefers-contrast) {
93+
.textRecognitionSuccessIcon {
94+
background-color: currentColor;
95+
border-color: currentColor;
96+
fill: --in-content-page-background;
97+
}
98+
}
99+
100+
@keyframes throbber-animation-ltr {
101+
0% { transform: translateX(0); }
102+
100% { transform: translateX(-100%); }
103+
}
104+
105+
@keyframes throbber-animation-rtl {
106+
0% { transform: translateX(0); }
107+
100% { transform: translateX(100%); }
108+
}
109+
110+
@keyframes success-animation {
111+
0% {
112+
transform: scale(0);
113+
opacity: 0;
114+
}
115+
100% {
116+
transform: scale(1);
117+
opacity: 1;
118+
}
119+
}

browser/components/textrecognition/textrecognition.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,37 @@
66
<html>
77
<head>
88
<meta charset="utf-8">
9+
<meta http-equiv="Content-Security-Policy"
10+
content="default-src chrome:; object-src 'none';">
11+
<link rel="stylesheet" type="text/css"
12+
href="chrome://global/skin/in-content/common.css">
913
<link rel="stylesheet" type="text/css"
1014
href="chrome://browser/content/textrecognition/textrecognition.css">
15+
<link rel="localization" href="browser/textRecognition.ftl"/>
1116
<script type="module" src="chrome://browser/content/textrecognition/textrecognition.mjs"></script>
17+
<!-- The title is available to screen readers only -->
18+
<title data-l10n-id="text-recognition-modal-accessible-modal-title"></title>
1219
</head>
1320
<body>
21+
<div class="textRecognition">
22+
<div class="textRecognitionHeader" id="text-recognition-header-loading"">
23+
<span class="textRecognitionThrobber"></span>
24+
<span data-l10n-id="text-recognition-modal-searching-title"></span>
25+
</div>
26+
<div class="textRecognitionHeader" id="text-recognition-header-results">
27+
<img class="textRecognitionSuccessIcon" src="chrome://global/skin/icons/check.svg" role="presentation"/>
28+
<span data-l10n-id="text-recognition-modal-results-title"></span>
29+
</div>
30+
<div class="textRecognitionHeader" id="text-recognition-header-no-results">
31+
<img class="textRecognitionNoResultIcon" src="chrome://global/skin/icons/warning.svg" role="presentation"/>
32+
<span data-l10n-id="text-recognition-modal-no-results-title">
33+
<a data-l10n-name="error-link" href="https://support.mozilla.org/%LOCALE%/kb/placeholder5"></a>
34+
</span>
35+
</div>
36+
<div class="textRecognitionText" role="document"></div>
37+
<div class="textRecognitionFooter">
38+
<button data-l10n-id="text-recognition-modal-close-button" type="button" id="text-recognition-close" class="primary"></button>
39+
</div>
40+
</div>
1441
</body>
1542
</html>

0 commit comments

Comments
 (0)