Fix Bug 1432657 - Add pocket card type to highlight types #3975
Conversation
22867b3
to
1af05e2
|
Seems like there's some open design questions as well as checking with pocket people on the behaviors / consistent UX across their products. |
| @@ -54,6 +55,7 @@ confirm_history_delete_p1=Are you sure you want to delete every instance of this | |||
| # page from history. | |||
| confirm_history_delete_notice_p2=This action cannot be undone. | |||
| menu_action_save_to_pocket=Save to Pocket | |||
| menu_action_remove_pocket=Remove from Pocket List | |||
Mardak
Feb 13, 2018
Member
Probably confirm with pocket(?) about this string. In particular the opposite string is just "Save to Pocket" (no "List")
Probably confirm with pocket(?) about this string. In particular the opposite string is just "Save to Pocket" (no "List")
sarracini
Feb 16, 2018
Author
Contributor
Designers said "Delete on Pocket" and "Archive on Pocket"
Designers said "Delete on Pocket" and "Archive on Pocket"
| @@ -29,6 +29,7 @@ type_label_visited=Visited | |||
| type_label_bookmarked=Bookmarked | |||
| type_label_synced=Synced from another device | |||
| type_label_recommended=Trending | |||
| type_label_pocket=Saved To Pocket | |||
Mardak
Feb 13, 2018
Member
Probably also confirm with pocket people on their terminology.
Probably also confirm with pocket people on their terminology.
Mardak
Feb 22, 2018
Member
Noted on IRC that this should have lowercase "t" for "to"
Noted on IRC that this should have lowercase "t" for "to"
| } | ||
| try { | ||
| // If the user is logged in, just save the link to Pocket and update the page | ||
| let {item_id} = await this.addLinkToPocket(url, title); |
Mardak
Feb 13, 2018
Member
What is the expected behavior of saving to pocket? Before, it would open up the tagging doorhanger and trigger the library animation.
What is the expected behavior of saving to pocket? Before, it would open up the tagging doorhanger and trigger the library animation.
Mardak
Feb 13, 2018
Member
Note that the bookmark behavior is to open the bookmark doorhanger that triggers the library animation.
Note that the bookmark behavior is to open the bookmark doorhanger that triggers the library animation.
sarracini
Feb 14, 2018
Author
Contributor
While we wait for the ui wanted for the correct behaviour, I'll explain my reasoning behind this change..
calling Pocket.savePage although does drop the doorhanger down doesn't have any indication of a successful or not successful save once it goes off and does it's stuff. With the pktApi we get the pocket_id back when we're successful so we can update the card we just saved, similar to how we do that for bookmark (i.e changing the context menu + highlight context) So I traded off one kind of confirmation feedback for a different one. Ideally we would call addLinkToPocket, and then also call something in Pocket.jsm to just show the doorhanger + library animation.
While we wait for the ui wanted for the correct behaviour, I'll explain my reasoning behind this change..
calling Pocket.savePage although does drop the doorhanger down doesn't have any indication of a successful or not successful save once it goes off and does it's stuff. With the pktApi we get the pocket_id back when we're successful so we can update the card we just saved, similar to how we do that for bookmark (i.e changing the context menu + highlight context) So I traded off one kind of confirmation feedback for a different one. Ideally we would call addLinkToPocket, and then also call something in Pocket.jsm to just show the doorhanger + library animation.
sarracini
Feb 16, 2018
Author
Contributor
The designers say don't bother with the doorhanger :D
The designers say don't bother with the doorhanger :D
| @@ -112,14 +111,20 @@ this.HighlightsFeed = class HighlightsFeed { | |||
| this.fetchImage(page); | |||
| } | |||
|
|
|||
| // When we bookmark something it adds a history entry - so adjust the type | |||
Mardak
Feb 13, 2018
Member
This comment is a bit misleading. The reason why the type switches to "bookmark" is that a highlight that comes in as history/visited might happen to be bookmarked, so show it as bookmarked even though the source was from history.
This comment is a bit misleading. The reason why the type switches to "bookmark" is that a highlight that comes in as history/visited might happen to be bookmarked, so show it as bookmarked even though the source was from history.
sarracini
Feb 14, 2018
Author
Contributor
These were my steps to reproduce for this that caused me to write this comment (on a clean profile):
- Bookmark a trending pocket story from the context menu
- Open debugger and set a breakpoint in HighlightsFeed.jsm right after we dedupe against top sites
- Force a refresh in Higlights (I dismissed another trending story)
- Observe
this.store.getState().TopSites.rows and see that the first item in the array is the bookmarked trending story with type 'history' ... even though I've never actually visited it.
So it's a bit confusing that it's there even though I never actually visited the page. How about "Adjust the type for 'history' items that are also 'bookmarked'" for the comment?
These were my steps to reproduce for this that caused me to write this comment (on a clean profile):
- Bookmark a trending pocket story from the context menu
- Open debugger and set a breakpoint in HighlightsFeed.jsm right after we dedupe against top sites
- Force a refresh in Higlights (I dismissed another trending story)
- Observe
this.store.getState().TopSites.rowsand see that the first item in the array is the bookmarked trending story with type 'history' ... even though I've never actually visited it.
So it's a bit confusing that it's there even though I never actually visited the page. How about "Adjust the type for 'history' items that are also 'bookmarked'" for the comment?
| @@ -289,6 +305,7 @@ function Sections(prevState = INITIAL_STATE.Sections, action) { | |||
| return prevState.map(section => Object.assign({}, section, | |||
| {rows: section.rows.filter(site => !action.data.includes(site.url))})); | |||
| case at.PLACES_LINK_BLOCKED: | |||
| case at.REMOVE_FROM_POCKET: | |||
| return prevState.map(section => | |||
| Object.assign({}, section, {rows: section.rows.filter(site => site.url !== action.data.url)})); | |||
Mardak
Feb 13, 2018
Member
Hmm.. Removing a specific pocket item isn't the same as blocking a url.. where this code would hide any other bookmarks of the same url when unpocketing.
Hmm.. Removing a specific pocket item isn't the same as blocking a url.. where this code would hide any other bookmarks of the same url when unpocketing.
| icon: "remove-pocket", | ||
| action: ac.AlsoToMain({ | ||
| type: at.REMOVE_FROM_POCKET, | ||
| data: {pocket_id: site.pocket_id, url: site.url} |
Mardak
Feb 13, 2018
Member
If we make the reducer remove by pocket_id then we won't need url here anymore.
If we make the reducer remove by pocket_id then we won't need url here anymore.
|
Notes from the UX meeting
|
| @@ -86,8 +89,7 @@ this.HighlightsFeed = class HighlightsFeed { | |||
|
|
|||
| // Request more than the expected length to allow for items being removed by | |||
| // deduping against Top Sites or multiple history from the same domain, etc. | |||
| // Until bug 1425496 lands, do not include saved Pocket items in highlights | |||
| const manyPages = await this.linksCache.request({numItems: MANY_EXTRA_LENGTH, excludePocket: true}); | |||
| const manyPages = await this.linksCache.request({numItems: MANY_EXTRA_LENGTH, excludePocket: options.excludePocket}); | |||
Mardak
Feb 16, 2018
Member
Mmm… Doesn't this mean we only include pocket items for the one refresh out of the ~12 each hour? So most highlight updates result in no pocket items shown?
Mmm… Doesn't this mean we only include pocket items for the one refresh out of the ~12 each hour? So most highlight updates result in no pocket items shown?
sarracini
Feb 16, 2018
Author
Contributor
Other way around, no? We want to update pocket on every refresh except the system_tick unless it's been over an hour... so if options.excludePocket is null for all refreshes, then !excludePocket should be true and then we'd go fetch them in NewTabUtils
Other way around, no? We want to update pocket on every refresh except the system_tick unless it's been over an hour... so if options.excludePocket is null for all refreshes, then !excludePocket should be true and then we'd go fetch them in NewTabUtils
|
As discussed on irc, we'll want to add a pocket in-memory cache to |
|
blocked on bug 1439684: https://bugzilla.mozilla.org/show_bug.cgi?id=1439684 |
|
Given the Pocket team's desire to have sync instead of polling, we probably should have a pref that toggles |
| @@ -130,6 +130,10 @@ const PREFS_CONFIG = new Map([ | |||
| title: "Boolean flag that decides whether or not to show the topstories disclaimer.", | |||
| value: true | |||
| }], | |||
| ["section.highlights.excludePocket", { | |||
sarracini
Feb 21, 2018
Author
Contributor
Not sure about what namespace we want for the "sub-option" prefs
Not sure about what namespace we want for the "sub-option" prefs
Mardak
Feb 21, 2018
Member
I guess it matches "section.highlights.collapsed" although we also have "browser.newtabpage.activity-stream.collapseTopSites"…
Let's keep it next to the other highlights pref. And perhaps rename it to "includePocket" as that's what the UI would expose.
I guess it matches "section.highlights.collapsed" although we also have "browser.newtabpage.activity-stream.collapseTopSites"…
Let's keep it next to the other highlights pref. And perhaps rename it to "includePocket" as that's what the UI would expose.
90e7d15
to
3f3112d
|
Main thing is fixing up |
| CheckPinTopSite: (site, index) => (site.isPinned ? LinkMenuOptions.UnpinTopSite(site) : LinkMenuOptions.PinTopSite(site, index)), | ||
| CheckSavedToPocket: (site, index) => (site.pocket_id ? LinkMenuOptions.DeleteFromPocket(site) : LinkMenuOptions.SaveToPocket(site, index)), | ||
| CheckBookmarkOrArchive: site => (site.pocket_id ? LinkMenuOptions.ArchiveFromPocket(site) : LinkMenuOptions.CheckBookmark(site)), | ||
| CheckDeleteHistoryOrEmpty: (site, index, eventSource) => (site.pocket_id ? LinkMenuOptions.EmptyItem() : LinkMenuOptions.DeleteUrl(site, index, eventSource)) |
Mardak
Feb 22, 2018
Member
Not sure if this is any better with a helper, so we can do something like…
{
CheckBookmark: check("bookmarkGuid", "RemoveBookmark", "AddBookmark"),
CheckDeleteHistoryOrEmpty: check("pocket_id", "EmptyItem", "DeleteUrl")
}
If we want to have the expressiveness of potentially checking all 3 site, index, eventSource (in the future?), the first argument to check could be a callback instead of just a string.
Not sure if this is any better with a helper, so we can do something like…
{
CheckBookmark: check("bookmarkGuid", "RemoveBookmark", "AddBookmark"),
CheckDeleteHistoryOrEmpty: check("pocket_id", "EmptyItem", "DeleteUrl")
}If we want to have the expressiveness of potentially checking all 3 site, index, eventSource (in the future?), the first argument to check could be a callback instead of just a string.
| @@ -29,6 +29,7 @@ type_label_visited=Visited | |||
| type_label_bookmarked=Bookmarked | |||
| type_label_synced=Synced from another device | |||
| type_label_recommended=Trending | |||
| type_label_pocket=Saved To Pocket | |||
Mardak
Feb 22, 2018
Member
Noted on IRC that this should have lowercase "t" for "to"
Noted on IRC that this should have lowercase "t" for "to"
| @@ -34,7 +34,7 @@ export class ContextMenu extends React.PureComponent { | |||
| <ul role="menu" className="context-menu-list"> | |||
| {this.props.options.map((option, i) => (option.type === "separator" ? | |||
| (<li key={i} className="separator" />) : | |||
| (<ContextMenuItem key={i} option={option} hideContext={this.hideContext} />) | |||
| (option.type !== "empty" && <ContextMenuItem key={i} option={option} hideContext={this.hideContext} />) | |||
Mardak
Feb 22, 2018
Member
Seems like we want to have a switch (option.type) or .forEach instead of .map, but this is fine.
Seems like we want to have a switch (option.type) or .forEach instead of .map, but this is fine.
sarracini
Feb 23, 2018
Author
Contributor
I'm assuming some of this is going to change anyways with weighted highlights, since we'll have to have a way to assign context menu options on a per card basis and we won't need this empty stuff anymore
I'm assuming some of this is going to change anyways with weighted highlights, since we'll have to have a way to assign context menu options on a per card basis and we won't need this empty stuff anymore
| @@ -66,7 +66,7 @@ const BUILT_IN_SECTIONS = { | |||
| icon: "highlights", | |||
| title: {id: "header_highlights"}, | |||
| maxRows: 3, | |||
| availableContextMenuOptions: ["CheckBookmark", "SaveToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl", "DeleteUrl"], | |||
| availableContextMenuOptions: ["CheckBookmarkOrArchive", "CheckSavedToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl", "CheckDeleteHistoryOrEmpty"], | |||
Mardak
Feb 22, 2018
Member
We want these "Check" versions for topstories.availableContextMenuOptions too for the in-page update. (Fortunately, topstories already doesn't have "DeleteUrl" :p)
We want these "Check" versions for topstories.availableContextMenuOptions too for the in-page update. (Fortunately, topstories already doesn't have "DeleteUrl" :p)
| } | ||
| return prevState.map(section => Object.assign({}, section, { | ||
| rows: section.rows.map(item => { | ||
| if (item.url === action.data.url) { |
Mardak
Feb 22, 2018
Member
There's a slight bug / accidental(?) fix here in that if you pocket a story, stories' rows gets deduped via SECTION_UPDATE. A similar thing happens when bookmarking that @piatra and @csadilek worked on.
The bug is that even when Highlights no longer has the deduping url, e.g., archived pocket or unbookmarked page+delete history, rows is still deduped until it gets refreshed with an update or restart.
Simplest steps to reproduce:
- save to pocket a story
- archive that card
- refresh page see that the card is still gone
- toggle stories section from preferences, and see the story come back
Probably not really worth a fix as the user wanted it gone anyway and would most likely only run into it on restarting firefox, and by then, hopefully new stories would have come in…
There's a slight bug / accidental(?) fix here in that if you pocket a story, stories' rows gets deduped via SECTION_UPDATE. A similar thing happens when bookmarking that @piatra and @csadilek worked on.
The bug is that even when Highlights no longer has the deduping url, e.g., archived pocket or unbookmarked page+delete history, rows is still deduped until it gets refreshed with an update or restart.
Simplest steps to reproduce:
- save to pocket a story
- archive that card
- refresh page see that the card is still gone
- toggle stories section from preferences, and see the story come back
Probably not really worth a fix as the user wanted it gone anyway and would most likely only run into it on restarting firefox, and by then, hopefully new stories would have come in…
sarracini
Feb 23, 2018
Author
Contributor
Ah I see, yeah that's unfortunate but I think you're right, not super important to fix. Unless we added the saved to pocket trending card to the block list when they archive or save it or something. But probably not worth fixing right now
Ah I see, yeah that's unfortunate but I think you're right, not super important to fix. Unless we added the saved to pocket trending card to the block list when they archive or save it or something. But probably not worth fixing right now

Has the same behaviour as when you bookmark a trending story - update the card itself then next time you refresh it shows it in the highlights section