Skip to content
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

Manifest V3 fixes #193

Merged
merged 1 commit into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions app/assets/_locales/en/messages.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"appDesc": {
"message": "Collaborative, real-time fact-checking.",
"message": "Collaborative, real-time fact-checking.",
"description": "The description of the application, displayed in the web store."
},
"settingYoutubeOverlay": {
"message": "YouTube Overlay",
"message": "YouTube Overlay",
"description": "Setting to activate the video overlay on YouTube."
},
"openOnCF": {
"message": "Open this video on CaptainFact.io",
"message": "Open this video on CaptainFact.io",
"description": "Status label when button is disactivated."
},
"settings": {
"message": "Settings",
"message": "Settings",
"description": "Title of the settings header."
},
"videos": {
Expand All @@ -22,5 +22,17 @@
"noVideoAvailable": {
"message": "No video available, but you can still check on the website:",
"description": "Message displayed when there is no video available"
},
"requestPermissions": {
"message": "We need some additional permissions to use CaptainFact on YouTube.",
"description": "Message to request permissions"
},
"btnGrantPermissions": {
"message": "Grant permissions",
"description": "Ok button"
},
"btnNoPermissions": {
"message": "Dismiss",
"description": "No button"
}
}
20 changes: 16 additions & 4 deletions app/assets/_locales/fr/messages.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"appDesc": {
"message": "Vérification d'information collaborative en temps réel.",
"message": "Vérification d'information collaborative en temps réel.",
"description": "The description of the application, displayed in the web store."
},
"settingYoutubeOverlay": {
"message": "Intégration dans YouTube",
"message": "Intégration dans YouTube",
"description": "Setting to activate the video overlay on YouTube."
},
"openOnCF": {
"message": "Ouvrir cette vidéo sur CaptainFact.io",
"message": "Ouvrir cette vidéo sur CaptainFact.io",
"description": "Status label when button is disactivated."
},
"settings": {
"message": "Préférences",
"message": "Préférences",
"description": "Title of the settings header."
},
"videos": {
Expand All @@ -22,5 +22,17 @@
"noVideoAvailable": {
"message": "Il n'y a aucune vidéo par ici. Essayez de jeter un coup d'oeuil sur le site :",
"description": "Message displayed when there is no video available"
},
"requestPermissions": {
"message": "Pour utiliser les fonctionnalités de CaptainFact sur YouTube, nous avons besoin de votre autorisation.",
"description": "Message to request permissions"
},
"btnGrantPermissions": {
"message": "Ok",
"description": "Bouton Ok"
},
"btnNoPermissions": {
"message": "Ignorer",
"description": "Bouton Non"
}
}
23 changes: 20 additions & 3 deletions app/components/Button.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
font-size: 1.25em;
font-size: 1em;
height: 1.5em;
line-height: 1.5;
position: relative;
Expand All @@ -29,11 +29,16 @@
padding: calc(0.375em - 1px) 0.75em;
text-align: center;
white-space: nowrap;
border-color: #6ba3a7;
border-radius: 4px;
padding: 0.8em 1em;
color: #6ba3a7;
}

.button:hover {
border-color: #b5b5b5;
color: #363636;
background-color: #6ba3a7;
border-color: #6ba3a7;
color: #fff;
}

.button.active {
Expand All @@ -45,4 +50,16 @@

.button.active[data-value=OFF] {
background-color: #f73d57;
}

.primary {
background-color: #6ba3a7;
border-color: #0000;
color: #fff;
}

.primary:hover {
background-color: #639ea2;
border-color: #0000;
color: #fff;
}
66 changes: 66 additions & 0 deletions app/components/GrantPermissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react'
import { BrowserExtension } from '../lib/browser-extension'
import LocalSettings from '../lib/local_settings'
import translate from '../lib/translate'
import buttonStyles from './Button.css'
import classNames from 'classnames'
import { FRONTEND_URL } from 'config'
import { domainToHostWildCard } from '../lib/url_utils'

const EXPECTED_ORIGINS = [
'*://www.youtube.com/*',
'*://m.youtube.com/*',
domainToHostWildCard(FRONTEND_URL),
]

export const checkHasAllDomainsPermissions = async () => {
return new Promise((resolve) => {
BrowserExtension.permissions.contains(
{ origins: EXPECTED_ORIGINS },
(result) => resolve(result)
)
})
}

export const GrantPermissions = ({ onClose, canDismiss = true }) => {
return (
<div style={{ padding: '16px 32px', fontSize: '18px' }}>
<p>{translate('requestPermissions')}</p>
<div
style={{
display: 'flex',
gap: '8px',
justifyContent: 'center',
marginTop: '24px',
}}
>
<button
className={classNames(buttonStyles.button, buttonStyles.primary)}
onClick={() =>
BrowserExtension.permissions.request(
{ origins: EXPECTED_ORIGINS },
(granted) => {
if (granted) {
onClose()
}
}
)
}
>
{translate('btnGrantPermissions')}
</button>
{canDismiss && (
<button
className={buttonStyles.button}
onClick={() => {
LocalSettings.setValue('dismissPermissionWarning', true)
onClose()
}}
>
{translate('btnNoPermissions')}
</button>
)}
</div>
</div>
)
}
63 changes: 46 additions & 17 deletions app/components/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,48 @@ import translate from '../lib/translate'
import VideosList from './VideosList'
import ExternalLink from './ExternalLink'
import { BrowserExtension } from '../lib/browser-extension'
import {
GrantPermissions,
checkHasAllDomainsPermissions,
} from './GrantPermissions'
import LocalSettings from '../lib/local_settings'

export default class Popup extends React.Component {
render() {
return (
<div className={styles.popup}>
<ExternalLink
href="https://captainfact.io/videos"
className={styles.bannerLink}
>
<img
src={BrowserExtension.runtime.getURL('img/banner.jpg')}
className={styles.banner}
alt="CaptainFact"
/>
</ExternalLink>
const checkIfPermissionsWarningShouldBeShown = async () => {
const hasPermissions = await checkHasAllDomainsPermissions()
if (!hasPermissions) {
if (!(await LocalSettings.getValue('dismissPermissionWarning'))) {
return true
}
}

return false
}

const Popup = () => {
const [showPermissionsWarning, setShowPermissionsWarning] =
React.useState(false)

React.useEffect(() => {
checkIfPermissionsWarningShouldBeShown().then((showWarning) => {
setShowPermissionsWarning(showWarning)
})
}, [])

return (
<div className={styles.popup}>
<ExternalLink
href="https://captainfact.io/videos"
className={styles.bannerLink}
>
<img
src={BrowserExtension.runtime.getURL('img/banner.jpg')}
className={styles.banner}
alt="CaptainFact"
/>
</ExternalLink>
{showPermissionsWarning ? (
<GrantPermissions onClose={() => setShowPermissionsWarning(false)} />
) : (
<Tabs
defaultIndex={0}
selectedTabClassName={tabsStyles.isActive}
Expand Down Expand Up @@ -54,7 +81,9 @@ export default class Popup extends React.Component {
</div>
</TabPanel>
</Tabs>
</div>
)
}
)}
</div>
)
}

export default Popup
4 changes: 4 additions & 0 deletions app/components/Select.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@
.select > * {
border-top: none;
border-bottom: none;
}

.select > a {
border-radius: 0;
}
17 changes: 16 additions & 1 deletion app/components/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import styles from './Settings.css'
import LocalSettings from '../lib/local_settings.js'
import translate from '../lib/translate.js'
import BrowserIconBadgeCounter from '../lib/browser_icon_badge_counter.js'
import {
GrantPermissions,
checkHasAllDomainsPermissions,
} from './GrantPermissions.js'

const SELECT_OPTIONS_ON_OFF = {
ON: true,
Expand All @@ -14,11 +18,14 @@ const SELECT_OPTIONS_ON_OFF = {
export default class Settings extends React.Component {
constructor(props) {
super(props)
this.state = { settings: null }
this.state = { settings: null, hasDomainsPermission: true }
}

componentDidMount() {
LocalSettings.load().then((settings) => this.setState({ settings }))
checkHasAllDomainsPermissions().then((hasDomainsPermission) =>
this.setState({ hasDomainsPermission })
)
}

handleChange(key, value) {
Expand Down Expand Up @@ -59,6 +66,14 @@ export default class Settings extends React.Component {
options={SELECT_OPTIONS_ON_OFF}
/>
</div>
{!this.state.hasDomainsPermission && (
<div className={styles.control}>
<GrantPermissions
canDismiss={false}
onClose={() => this.setState({ hasDomainsPermission: true })}
/>
</div>
)}
</div>
)
}
Expand Down
5 changes: 3 additions & 2 deletions app/entrypoints/popup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { createRoot } from 'react-dom/client'
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'

import { CF_API_URL } from '../lib/constants'
Expand All @@ -16,4 +16,5 @@ const App = () => (
)

// Render popup
ReactDOM.render(<App />, document.querySelector('#root'))
const root = createRoot(document.getElementById('root'))
root.render(<App />)
29 changes: 7 additions & 22 deletions app/lib/browser_icon_badge_counter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ export default class BrowserIconBadgeCounter {
* Reset / remove badge text
* @param {function() {...}} callback
*/
static reset() {
return new Promise((fulfill) => {
fulfill(setBadgeText(''))
})
static async reset() {
return BrowserExtension.action.setBadgeText({ text: '' })
}

/**
Expand All @@ -24,30 +22,17 @@ export default class BrowserIconBadgeCounter {
return LocalSettings.getValue('newVideosBadge').then((isActivated) => {
if (!isActivated) return null

return BrowserExtension.browserAction.getBadgeText(
{},
(currentValueStr) => {
const intValue = decodeValue(currentValueStr)
const newValueStr = encodeValue(intValue + value)
return setBadgeText(newValueStr)
}
)
return BrowserExtension.action.getBadgeText({}, (currentValueStr) => {
const intValue = decodeValue(currentValueStr) || 0
const newValueStr = encodeValue(intValue + value)
return BrowserExtension.action.setBadgeText({ text: newValueStr })
})
})
}
}

// Private functions

/**
* Set the given `text` as extension's icon badge. To remove the badge, send an
* empty string here.
*
* @param {string} text : a 0-4 characters string of the text to display
*/
function setBadgeText(text) {
return BrowserExtension.browserAction.setBadgeText({ text })
}

/**
* @param {string} value : Encoded value
* @returns {integer} parsed value or 0 if empty / bad format
Expand Down
Loading