New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Search Injection #320
Conversation
|
Ah snap, that is because of the DOM element which is used to append the results hasn't been loaded on the page yet. ( Temporary fix: Try refreshing the page ) Am working on a proper fix for that. @oliversauter |
c04b69e
to
74badee
Compare
|
Just gave it a test and works wonderfully now! Will leave some design notes in the issue itself, because now I have the designs for it :) |
8f022b3
to
9c37f2e
Compare
|
@oliversauter Check it out now. Prepended the css and can change positions. Have some UI tweaks left to do. |
|
Hey Sriram, thanks for updating your PR! Just checked on it, still seem the same issue with the loading, and some others I uncovered:
|
ccf113f
to
237fa10
Compare
src/search-injection/constants.js
Outdated
| @@ -18,7 +18,7 @@ export const SEARCH_ENGINES = { | |||
| google: { | |||
| regex: /(http[s]?:\/\/)?(www.)?google[.\w]+\/search\?.*/, | |||
| container: { | |||
| above: 'center_col', | |||
| above: 'res', | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appending to res makes Memex Container go below ads. Did you see that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed it again, thanks for the headsup!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty awesome work @digi0ps and @oliversauter ! Code is pretty impressive. I built and tried it out, and my experience using it was really good. Very smooth, and cool how you can move it around.
I would postpone the screenshots for now. In the current index it is very painful to get them as you need to bring in Pouch and fetch the data for each result. In the new index, they are returned with the rest of the search results, so it will just be a matter of rendering them straight in a <img> somewhere once we merge that in
src/background.js
Outdated
| @@ -44,6 +45,13 @@ async function openOverview() { | |||
| } | |||
| } | |||
|
|
|||
| const openOverviewURL = url => chrome.tabs.create({ url }) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everywhere you've used the chrome global, replace it with browser for consistency with the rest of codebase. They provide similar APIs, although we're using the web ext polyfill (assigned to browser) as it provides more consistency across browsers and uses Promises for async stuff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, with the openOverviewURL function, why does it differ from openOptionsURL function in taking an absolute URL rather than just the path? I think you could simplify it a lot by just hardcoding the overview URL in there and having a query arg to append to it. Then content script side just needs to send the query; no need to know what the URL is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah right. I didn't know why I did that .-.
I will update it!
src/options/settings/index.js
Outdated
| import SearchInjection from './components/SearchInjection' | ||
|
|
||
| const Settings = () => ( | ||
| <Wrapper> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think <Wrapper> should be needed here. This is a "noop" component; it renders nothing to the real DOM. Only used as a helper to make some JSX code neater. And if you can remove this, this whole module is just const Settings = () => <SearchInjection /> - so probably unnecessary.
Instead what you could do is separate the view parts of SearchInjection (everything in the render() method) into it's own dumb component and just have the other state-interacting methods within a SearchInjectionContainer class (render() would simply just render the dumb component and pass in the needed props). This is the general container-view pattern in React.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooh. I thought wrapper was for the UI. Great second point.
Will this be good: I do all the state related logic in Settings component and pass it to the SearchInjection component?
|
|
||
| const openSettings = () => { | ||
| const message = { | ||
| action: 'openOptionsURL', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to define these action names somewhere which is imported by both this content script code and the corresponding listener in the background script code. Maybe the search-injection/constants module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it.
| } | ||
|
|
||
| toggleDropDown() { | ||
| this.setState(state => ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're using both reducer and object versions of this.setState; it would be good to be consistent with which you use. In the rest of the code base we're trying to use the reducer (function) taking version. Really important to note though, if you use the reducer version like here: the returned value of the callback will be the new state.
this.setState(state => ({ dropdown: !state.dropdown }))The above will unset all the other state keys, like hideResults, meaing they will be undefined whenever they get accessed via this.state. That may be your intention here though, but it's often a gotcha with this.setState.
The following would ensure dropdown state is updated, and all other state keys are left alone:
this.setState(state => ({ ...state, dropdown: !state.dropdown }))| return null | ||
| } | ||
| return ( | ||
| <div |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, good to move this to its own view module. Separate the state interaction and views
|
|
||
| // Append content_script.css to the document | ||
| const cssFile = browser.extension.getURL('/content_script.css') | ||
| appendCss(cssFile) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a bit odd to have the appendCss logic - which prepends (possible naming issue) a <script> tag to the DOM - in the search-injection/utils module while the other DOM stuff is in this module. Maybe you could move appendCss and maybe also have a appendReactRoot function to their own search-injection/dom module or something. Just a code-layout suggestion; the actual code seems very well done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prepend was a very recent change, so forgive me on that. It injects CSS into the page, so I guess injectCSS would fit it. And that's a nice idea, I will do it.
| ReactDOM.render( | ||
| <Results | ||
| results={results.slice(0, limit)} | ||
| len={results.length} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
results.length will always be <=10 because of pagination. Instead, where you call handleRender, you can use payload.searchResult.totalCount to get the real number (maybe just pass in the entire payload.searchResult and pull out the needed args: const handleRender = ({ docs, totalCount }) => { )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
That sounds good!
… On Mar 20, 2018, at 20:04, Sriram ***@***.***> wrote:
@digi0ps commented on this pull request.
In src/options/settings/index.js:
> @@ -0,0 +1,12 @@
+import React from 'react'
+
+import { Wrapper } from 'src/common-ui/components'
+import SearchInjection from './components/SearchInjection'
+
+const Settings = () => (
+ <Wrapper>
Oooh. I thought wrapper was for the UI. Great second point.
Will this be good: I do all the state related logic in Settings component and pass it to the SearchInjection component?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
|
|
Ah I think you just need to set "getTotalCount" to true as an arg when you call search() and it will return that (now only passes "query")
… On Mar 20, 2018, at 20:15, Sriram ***@***.***> wrote:
@digi0ps commented on this pull request.
In src/search-injection/content_script.js:
> + const component = document.getElementById('memexResults')
+ if (component) component.parentNode.removeChild(component)
+
+ const target = document.createElement('div')
+ target.setAttribute('id', 'memexResults')
+ container.insertBefore(target, container.firstChild)
+
+ // Number of results to limit
+ const limit = constants.LIMIT[position]
+
+ // Render our React component on the target element
+ // Passing this same function so that it can change position
+ ReactDOM.render(
+ <Results
+ results={results.slice(0, limit)}
+ len={results.length}
Ah, I was planning to look into this issue, as it never showed me a length greater than 10.
But I don't think the there is a totalCount attribute in the payload received.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
|
bd16b60
to
0d2e46e
Compare
|
@poltak @oliversauter @ShishKabab Check it out and tell me if there anything else that needs to be done. Also, should I merge the commits? |
| } | ||
|
|
||
| async componentDidMount() { | ||
| const checked = await getLocalStorage(SEARCH_INJECTION_KEY, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would name this to something more descriptive. Deeper into the code I see a checkbox is checked, but it would be nice if I could see what it represents immediately, like userDidEnableResults (or probably something better.)
|
Notes to @poltak re the tracking:
|
package.json
Outdated
| @@ -71,6 +71,7 @@ | |||
| "reselect": "^3.0.1", | |||
| "response-to-data-url": "^0.1.0", | |||
| "rxjs": "^5.5.5", | |||
| "sinon": "^4.4.6", | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure sinon should be a dev dep. (yarn remove sinon && yarn add --dev sinon)
| import { getLocalStorage, setLocalStorage } from 'src/search-injection/utils' | ||
| import { SEARCH_INJECTION_KEY } from 'src/search-injection/constants' | ||
|
|
||
| class Container extends React.Component { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling the class just Container means you have to open it up and look inside to see what it does, as the name doesn't give much info. You also might want to add more containers in this dir later for whatever reason. Maybe SearchInjectionContainer would be better as it simply wraps around that view.
| } | ||
|
|
||
| const search = query => { | ||
| // query: (string) query to be search |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For code doc, I would advise getting familiar with jsdoc which is what we're using in the rest of the project. Not super urgent - comments are better than nothing! - but just to keep in mind for future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh okay, I will take a look at jsdoc.
|
@digi0ps there might have been a slight regression in one of the recent changes: content script throws an error now when it mounts the main React component as the props aren't being passed down anymore for some reason. Also I would remove any |
|
@oliversauter @poltak Should I squash any of the commits? |
d225e9d
to
52c41cc
Compare
Results are attached only after the DOM is loaded. elements weren't loaded.
Also: - Changed the way values are stored in localStorage. - Remove the need for background.js in search_injection
Also, - Removed fadeOut of RemovedTest. - Render React only when document has completed loading. - Change the logo used.
Also, link it in memex results.
Also, adds fade animation.
Also, cleans up content_script.js.
And, clean up background.js.
- trakcing when user disables - user flagged as active when they click a result or click show more to go to overview - all done from bg script via remote calls
- the settings gear icon had a weird grey background in FF that was sticking out
Also, ran yarn format to clean up code.
52c41cc
to
6d62a50
Compare
|
@oliversauter happy to merge this? (let me know and I can resolve the conflicts) |




Fixes #281
Implemented injecting Memex results along with Google Search results.
I've created a new module in
src/search-injectionwhere thecontent_scriptresides.The content script:
TODOs: