Skip to content

Commit

Permalink
feat(app): sync bookmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
LarchLiu committed Jul 13, 2023
1 parent bac1a92 commit 287f1d7
Show file tree
Hide file tree
Showing 16 changed files with 436 additions and 76 deletions.
3 changes: 3 additions & 0 deletions app/extension/chrome/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ settings:
uiLanguage: UI
promptsLanguage: Prompts
languageSettings: Languages
syncSettings: Sync
syncBookmarks: Bookmarks
syncGithub: Github
de: German
en: English
es: Spanish
Expand Down
3 changes: 3 additions & 0 deletions app/extension/chrome/locales/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ settings:
uiLanguage: 界面语言
promptsLanguage: 提示词语言
languageSettings: 语言设置
syncSettings: 同步设置
syncBookmarks: 书签
syncGithub: Github
de: 德语
en: 英语
es: 西班牙语
Expand Down
29 changes: 27 additions & 2 deletions app/extension/chrome/src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { errorMessage } from '@stargram/core/utils'
import { NotionDataStorage } from '@stargram/core/storage/notion'
import { WebCardByApi } from '@stargram/core/webCard'
import { WebInfoByApi } from '@stargram/core/webInfo'
import { Openai } from '@stargram/core/llm/openai'
import { SaveWebInfoChain } from '@stargram/core/chain/saveWebInfo'
import type { EmbeddingsInfo, VectorMetaData, SavedNotion } from '@stargram/core'
import { storageInfo } from '@stargram/core/storage'
Expand All @@ -11,6 +9,12 @@ import { llmInfo } from '@stargram/core/llm'
import type { ContentRequest, ListenerSendResponse, PageInfo, SwResponse } from '~/types'

const DEFAULT_STARGRAM_HUB = 'https://stargram.cc'
let stopSyncMarks = false
let stopSyncGithbu = false
let marksCount = 0
let currentMark = 0
let githubCount = 0
let currentGithub = 0

async function sendSavedStatus(res: SwResponse) {
chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
Expand Down Expand Up @@ -80,6 +84,27 @@ chrome.runtime.onMessage.addListener(async (request: ContentRequest, sender, sen
}
sendResponse({ message: 'checking' })
}
else if (action === 'syncBookmarks') {
if (request.data) {
const pageData = request.data
saveToDB(pageData).then((res) => {
chrome.runtime.sendMessage({
action: 'syncBookmarksResult',
data: res
})
}).catch((err) => {
chrome.runtime.sendMessage({
action: 'syncBookmarksResult',
data: err
})
})
sendResponse({ message: 'handling save to DB' })
}
else {
// console.log('Error: request.data is undefined.')
sendResponse({ message: 'Error: request.data is undefined.', error: true })
}
}
return true
})

Expand Down
6 changes: 6 additions & 0 deletions app/extension/chrome/src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const starFillSrc = 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F
const iconLanguage = 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="32" height="32" viewBox="0 0 32 32"%3E%3Cpath fill="currentColor" d="M16 28h-3c-3.9 0-7-3.1-7-7v-4h2v4c0 2.8 2.2 5 5 5h3v2zm12 2h2.2l-4.6-11h-2.2l-4.6 11H21l.8-2h5.3l.9 2zm-5.3-4l1.8-4.4l1.8 4.4h-3.6zM28 15h-2v-4c0-2.8-2.2-5-5-5h-4V4h4c3.9 0 7 3.1 7 7v4zM14 5V3H9V1H7v2H2v2h8.2c-.2.9-.8 2.5-2.2 4c-.6-.7-1.1-1.4-1.4-2H4.3c.4 1 1.1 2.2 2.1 3.3c-.8.7-2 1.3-3.4 1.8l.7 1.9c1.8-.7 3.2-1.5 4.3-2.3c1.1.9 2.5 1.7 4.3 2.3l.7-1.9c-1.4-.5-2.6-1.2-3.5-1.8c1.9-2 2.5-4.1 2.7-5.3H14z"%2F%3E%3C%2Fsvg%3E'
const iconSetting = 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1024" height="1024" viewBox="0 0 1024 1024"%3E%3Cpath fill="currentColor" d="M600.704 64a32 32 0 0 1 30.464 22.208l35.2 109.376c14.784 7.232 28.928 15.36 42.432 24.512l112.384-24.192a32 32 0 0 1 34.432 15.36L944.32 364.8a32 32 0 0 1-4.032 37.504l-77.12 85.12a357.12 357.12 0 0 1 0 49.024l77.12 85.248a32 32 0 0 1 4.032 37.504l-88.704 153.6a32 32 0 0 1-34.432 15.296L708.8 803.904c-13.44 9.088-27.648 17.28-42.368 24.512l-35.264 109.376A32 32 0 0 1 600.704 960H423.296a32 32 0 0 1-30.464-22.208L357.696 828.48a351.616 351.616 0 0 1-42.56-24.64l-112.32 24.256a32 32 0 0 1-34.432-15.36L79.68 659.2a32 32 0 0 1 4.032-37.504l77.12-85.248a357.12 357.12 0 0 1 0-48.896l-77.12-85.248A32 32 0 0 1 79.68 364.8l88.704-153.6a32 32 0 0 1 34.432-15.296l112.32 24.256c13.568-9.152 27.776-17.408 42.56-24.64l35.2-109.312A32 32 0 0 1 423.232 64H600.64zm-23.424 64H446.72l-36.352 113.088l-24.512 11.968a294.113 294.113 0 0 0-34.816 20.096l-22.656 15.36l-116.224-25.088l-65.28 113.152l79.68 88.192l-1.92 27.136a293.12 293.12 0 0 0 0 40.192l1.92 27.136l-79.808 88.192l65.344 113.152l116.224-25.024l22.656 15.296a294.113 294.113 0 0 0 34.816 20.096l24.512 11.968L446.72 896h130.688l36.48-113.152l24.448-11.904a288.282 288.282 0 0 0 34.752-20.096l22.592-15.296l116.288 25.024l65.28-113.152l-79.744-88.192l1.92-27.136a293.12 293.12 0 0 0 0-40.256l-1.92-27.136l79.808-88.128l-65.344-113.152l-116.288 24.96l-22.592-15.232a287.616 287.616 0 0 0-34.752-20.096l-24.448-11.904L577.344 128zM512 320a192 192 0 1 1 0 384a192 192 0 0 1 0-384zm0 64a128 128 0 1 0 0 256a128 128 0 0 0 0-256z"%2F%3E%3C%2Fsvg%3E'
const iconGithub = 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="16" height="16" viewBox="0 0 16 16"%3E%3Cpath fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59c.4.07.55-.17.55-.38c0-.19-.01-.82-.01-1.49c-2.01.37-2.53-.49-2.69-.94c-.09-.23-.48-.94-.82-1.13c-.28-.15-.68-.52-.01-.53c.63-.01 1.08.58 1.23.82c.72 1.21 1.87.87 2.33.66c.07-.52.28-.87.51-1.07c-1.78-.2-3.64-.89-3.64-3.95c0-.87.31-1.59.82-2.15c-.08-.2-.36-1.02.08-2.12c0 0 .67-.21 2.2.82c.64-.18 1.32-.27 2-.27c.68 0 1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82c.44 1.1.16 1.92.08 2.12c.51.56.82 1.27.82 2.15c0 3.07-1.87 3.75-3.65 3.95c.29.25.54.73.54 1.48c0 1.07-.01 1.93-.01 2.2c0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"%2F%3E%3C%2Fsvg%3E'
const iconSync = 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6c0 1.01-.25 1.97-.7 2.8l1.46 1.46A7.93 7.93 0 0 0 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6c0-1.01.25-1.97.7-2.8L5.24 7.74A7.93 7.93 0 0 0 4 12c0 4.42 3.58 8 8 8v3l4-4l-4-4v3z"%2F%3E%3C%2Fsvg%3E'
const iconPlay = 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="32" height="32" viewBox="0 0 32 32"%3E%3Cpath fill="currentColor" d="M7 28a1 1 0 0 1-1-1V5a1 1 0 0 1 1.482-.876l20 11a1 1 0 0 1 0 1.752l-20 11A1 1 0 0 1 7 28Z"%2F%3E%3C%2Fsvg%3E'
const iconStop = 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="32" height="32" viewBox="0 0 32 32"%3E%3Cpath fill="currentColor" d="M24 6H8a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2Z"%2F%3E%3C%2Fsvg%3E'
export {
GITHUB_DOMAIN,
GITHUB_URL,
Expand All @@ -15,5 +18,8 @@ export {
iconLanguage,
iconSetting,
iconGithub,
iconSync,
iconPlay,
iconStop,
version,
}
6 changes: 3 additions & 3 deletions app/extension/chrome/src/contentScript/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function startTwink() {
}
}
async function handleSaveToNotion() {
async function handleSaveToDB() {
// console.log('Handling save to Notion in the content script', document)
startTwink()
Expand Down Expand Up @@ -92,7 +92,7 @@ chrome.runtime.onMessage.addListener(async (request: SwRequest, sender, sendResp
// TODO: remove saveToDB from popup
if (action === 'saveToDB') {
handleSaveToNotion()
handleSaveToDB()
sendResponse({ message: 'Handling save to Notion in the content script', error: false })
}
else if (action === 'starredStatusToContent') {
Expand Down Expand Up @@ -187,7 +187,7 @@ function createButton(starred: boolean) {
gap: '0.5em',
})
a.addEventListener('click', () => {
handleSaveToNotion()
handleSaveToDB()
})
const icon = document.createElement('img')
icon.src = starred ? starFillSrc : starSrc
Expand Down
1 change: 1 addition & 0 deletions app/extension/chrome/src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"description": "Manage all your Starred Pages",
"permissions": [
"tabs",
"bookmarks",
"activeTab",
"storage",
"scripting"
Expand Down
155 changes: 151 additions & 4 deletions app/extension/chrome/src/popup/App.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { iconGithub, iconLanguage, iconSetting, starSrc, version } from '~/const'
import type { ListenerResponse } from '~/types'
import { iconGithub, iconLanguage, iconSetting, iconSync, iconPlay, iconStop, starSrc, version } from '~/const'
import type { ContentRequest, ListenerSendResponse, ListenerResponse } from '~/types'
import SelectConfig from '~/components/SelectConfig.vue'
const { t, locale } = useI18n()
const saveStatus = ref('')
const showSettings = ref(false)
const showLanguage = ref(false)
const showSync = ref(false)
const uiLangSelect = ref('en')
const userConfigInput = ref('')
const githubToken = ref('')
const userConfig = ref()
const promptsLangSelect = ref('en')
const saveBtn = ref<HTMLDivElement>()
const saveBtnEnable = ref(true)
const stopSyncMarks = ref(false)
const stopSyncGithbu = ref(false)
const marksCount = ref(0)
const currentMark = ref(0)
const githubCount = ref(0)
const currentGithub = ref(0)
let syncResultCount = 0
let bookMarks: { title: string; url: string | undefined}[] = []
let starTimer: NodeJS.Timeout
let bubblyTimer: NodeJS.Timeout
const colorPreset = [
Expand Down Expand Up @@ -77,6 +87,7 @@ function saveSettings() {
function onSettingsClick() {
showLanguage.value = false
showSync.value = false
showSettings.value = !showSettings.value
if (showSettings.value) {
chrome.storage.sync.get(['userConfig'], (result) => {
Expand All @@ -88,6 +99,7 @@ function onSettingsClick() {
}
function onLanguageClick() {
showSettings.value = false
showSync.value = false
showLanguage.value = !showLanguage.value
if (showLanguage.value) {
chrome.storage.sync.get(['uiLang', 'promptsLang'], (result) => {
Expand All @@ -97,6 +109,62 @@ function onLanguageClick() {
}
}
function onSyncClick() {
showSettings.value = false
showLanguage.value = false
showSync.value = !showSync.value
if (showSync.value) {
chrome.storage.sync.get(['githubToken'], (result) => {
githubToken.value = result.githubToken || ''
})
}
}
function getBookmarks(tree: chrome.bookmarks.BookmarkTreeNode[]) {
tree.map((item) => {
if (item.children) {
getBookmarks(item.children)
}
else {
marksCount.value++
bookMarks.push({
title: item.title,
url: item.url,
})
if (marksCount.value === 1) {
setTimeout(() => {
currentMark.value = 0
syncResultCount = 2
const pageInfo = {
webUrl: bookMarks[currentMark.value].url
}
chrome.runtime.sendMessage(
{
action: 'syncBookmarks',
data: pageInfo,
},
)
console.log(item.title, marksCount.value)
}, 1000)
}
}
})
}
function onBookmarksSync() {
chrome.bookmarks.getTree((bookmarkTreeNodes) => {
const bookmarkTree = bookmarkTreeNodes[0].children ?? []
marksCount.value = 0
currentMark.value = 0
bookMarks = []
getBookmarks(bookmarkTree)
})
}
function onGithubSync() {
}
function genRandomColor() {
randomColor1.value = colorPreset[Math.floor(Math.random() * 20)]
randomColor2.value = colorPreset[Math.floor(Math.random() * 20)]
Expand Down Expand Up @@ -152,6 +220,49 @@ onMounted(() => {
if (userConfigInput.value)
userConfig.value = JSON.parse(userConfigInput.value)
})
chrome.runtime.onMessage.addListener(async (request: ContentRequest, sender, sendResponse: ListenerSendResponse) => {
const action = request.action
if (action === 'syncBookmarksResult') {
let end = false
syncResultCount++
sendResponse({ message: 'ok' })
if (syncResultCount % 3 === 0 || (marksCount.value - (currentMark.value + 1) < 3)) {
syncResultCount = 0
for (let i = 0; i < 3; i++) {
if (currentMark.value < marksCount.value) {
if(!stopSyncMarks.value) {
currentMark.value++
const pageInfo = {
webUrl: bookMarks[currentMark.value].url
}
chrome.runtime.sendMessage(
{
action: 'syncBookmarks',
data: pageInfo,
},
)
console.log(bookMarks[currentMark.value].title, marksCount.value)
}
}
else {
end = true
break
}
}
}
if (end) {
const offset = 100
const duration = 3000
ElNotification({
title: 'Stargram',
type: 'success',
message: 'Sync Bookmars successful 👌',
offset,
duration,
})
}
}
})
})
</script>

Expand All @@ -169,13 +280,16 @@ onMounted(() => {
</div>
<footer class="mt-2 flex flex-col bg-[#f0f0f0] p-2 text-12px">
<div flex items-center justify-between>
<div flex>
<div flex items-center>
<div class="setting" cursor-pointer @click="onSettingsClick">
<img :src="iconSetting" height="18">
</div>
<div class="language" ml-2 cursor-pointer @click="onLanguageClick">
<img :src="iconLanguage" height="18">
</div>
<div class="sync" ml-2 cursor-pointer @click="onSyncClick">
<img :src="iconSync" height="20">
</div>
</div>
<div flex items-center>
<div class="github" mx-2 cursor-pointer>
Expand Down Expand Up @@ -256,6 +370,39 @@ onMounted(() => {
</select>
</div>
</div>
<div v-if="showSync" bg-white p-2 text-14px>
<div>{{ t('settings.syncSettings') }}</div>
<div class="divider" />
<div my-2 flex justify-between items-center>
<label class="inline-block h-5">{{ t('settings.syncBookmarks') }}</label>
<div flex items-cente>
<div v-if="currentMark < marksCount">
<div cursor-pointer @click="stopSyncMarks = !stopSyncMarks">
<img :src="stopSyncMarks ? iconPlay : iconStop" height="18">
</div>
</div>
<div class="sync-ping" ml-2 cursor-pointer @click="onBookmarksSync">
<img :src="iconSync" height="18">
</div>
</div>
</div>
<div my-2 flex justify-between items-center>
<div flex items-center>
<label class="inline-block h-5" pr-2>{{ t('settings.syncGithub') }}</label>
<input v-model="githubToken" text-12px placeholder="Github Token" type="password" name="githubToken">
</div>
<div flex items-center>
<div v-if="currentGithub < githubCount">
<div cursor-pointer @click="stopSyncGithbu = !stopSyncGithbu">
<img :src="stopSyncGithbu ? iconPlay : iconStop" height="18">
</div>
</div>
<div class="sync-ping" cursor-pointer @click="onGithubSync">
<img :src="iconSync" height="18">
</div>
</div>
</div>
</div>
</div>
</template>

Expand Down Expand Up @@ -339,7 +486,7 @@ onMounted(() => {
}
}
}
.sync:hover img,
.setting:hover img {
animation: spin 0.5s 0.5s;
}
Expand Down
2 changes: 1 addition & 1 deletion app/extension/chrome/src/popup/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
// Generated by unplugin-auto-import
export {}
declare global {

const ElNotification: typeof import('element-plus/es')['ElNotification']
}
12 changes: 12 additions & 0 deletions app/extension/chrome/src/popup/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ input {
border-style: solid;
}

::-webkit-input-placeholder { /* Edge */
color: #a6abb6;
}

:-ms-input-placeholder { /* Internet Explorer 10-11 */
color: #a6abb6;
}

::placeholder {
color: #a6abb6;
}

:root {
--el-color-primary: rgb(38, 22, 47);
--el-color-primary-light-3: rgb(98, 93, 100);
Expand Down
1 change: 1 addition & 0 deletions app/extension/chrome/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface SwResponse {
error?: string
tabId?: number
storageId?: string
url?: string
}

interface ListenerResponse {
Expand Down
Loading

1 comment on commit 287f1d7

@vercel
Copy link

@vercel vercel bot commented on 287f1d7 Jul 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

star-nexus – ./

star-nexus-larchliu.vercel.app
star-nexus-git-main-larchliu.vercel.app
star-nexus.vercel.app

Please sign in to comment.