Skip to content

Commit

Permalink
feat: init
Browse files Browse the repository at this point in the history
  • Loading branch information
leason-wan committed May 18, 2023
0 parents commit 07a73f0
Show file tree
Hide file tree
Showing 20 changed files with 7,636 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/submit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: "Submit to Web Store"
on:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Cache pnpm modules
uses: actions/cache@v3
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-
- uses: pnpm/action-setup@v2.2.4
with:
version: latest
run_install: true
- name: Use Node.js 16.x
uses: actions/setup-node@v3.4.1
with:
node-version: 16.x
cache: "pnpm"
- name: Build and zip extension artifact
run: pnpm package
- name: Browser Platform Publish
uses: PlasmoHQ/bpp@v3
with:
keys: ${{ secrets.SUBMIT_KEYS }}
artifact: build/chrome-mv3-prod.zip
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

#cache
.turbo
.next
.vercel

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*


# local env files
.env*

out/
build/
dist/

# plasmo - https://www.plasmo.com
.plasmo

# bpp - http://bpp.browser.market/
keys.json

# typescript
.tsbuildinfo
17 changes: 17 additions & 0 deletions .prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @type {import('prettier').Options}
*/
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: false,
trailingComma: "none",
bracketSpacing: true,
bracketSameLine: true,
plugins: [require.resolve("@plasmohq/prettier-plugin-sort-imports")],
importOrder: ["^@plasmohq/(.*)$", "^~(.*)$", "^[./]"],
importOrderSeparation: true,
importOrderSortSpecifiers: true
}
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Flomo Chat

![flomo chat](https://github.com/leason-wan/flomo-chat/blob/main/assets/preview.png?raw=true)
Binary file added assets/FC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/iconF.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions components/Text.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<script lang="ts" setup>
import { computed, ref } from 'vue'
import MarkdownIt from 'markdown-it'
import mdKatex from '@traptitech/markdown-it-katex'
import mila from 'markdown-it-link-attributes'
import hljs from 'highlight.js'
interface Props {
inversion?: boolean
error?: boolean
text?: string
loading?: boolean
asRawText?: boolean
}
const props = defineProps<Props>()
const textRef = ref<HTMLElement>()
const mdi = new MarkdownIt({
linkify: true,
highlight(code, language) {
const validLang = !!(language && hljs.getLanguage(language))
if (validLang) {
const lang = language ?? ''
return highlightBlock(hljs.highlight(code, { language: lang }).value, lang)
}
return highlightBlock(hljs.highlightAuto(code).value, '')
},
})
mdi.use(mila, { attrs: { target: '_blank', rel: 'noopener' } })
mdi.use(mdKatex, { blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000' })
const wrapClass = computed(() => {
return [
'text-wrap',
'rounded-md',
'px-3 py-2 mb-6',
{ 'w-full': props.inversion },
props.inversion ? 'bg-[#55bb8e]' : 'bg-[#f4f6f8]',
props.inversion ? 'bg-[#55bb8e]' : 'bg-[#f4f6f8]',
props.inversion ? 'text-white' : 'text-black',
]
})
const text = computed(() => {
const value = props.text ?? ''
if (!props.asRawText)
return mdi.render(value)
return value
})
function highlightBlock(str: string, lang?: string) {
return `<pre class="code-block-wrapper"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">${t('chat.copyCode')}</span></div><code class="hljs code-block-body ${lang}">${str}</code></pre>`
}
defineExpose({ textRef })
</script>

<template>
<div class="flex" :class="[{'flex-row-reverse': !inversion}]">
<div class="text-black" :class="wrapClass">
<div ref="textRef" class="leading-relaxed break-words">
<div v-if="!inversion" class="markdown-body" v-html="text" />
<div v-else class="whitespace-pre-wrap" v-html="text" />
<template v-if="loading">
<span class="dark:text-white w-[4px] h-[20px] block animate-blink" />
</template>
</div>
</div>
</div>
</template>
125 changes: 125 additions & 0 deletions contents/Index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<script lang="ts">
import themeText from "data-text:./theme.css"
import cssText from "data-text:element-plus/dist/index.css"
import cssCustom from "data-text:./index.css"
import type { PlasmoContentScript } from "plasmo"
export const config: PlasmoContentScript = {
matches: ["https://v.flomoapp.com/*"],
}
export default {
plasmo: {
getStyle() {
const style = document.createElement("style")
style.textContent = themeText + cssText + cssCustom
return style
}
},
}
</script>

<script lang="ts" setup>
import { ElForm, ElFormItem, ElButton, ElDrawer, ElInput } from 'element-plus'
import { Promotion, DArrowLeft, Switch } from '@element-plus/icons-vue'
import { reactive, ref } from 'vue'
import type { FormInstance } from 'element-plus'
import Text from '../components/Text.vue'
import { describe } from './bot'
import { setOpenAIApiKey, handleInit, store as chatStore, memoLoading, qaChat } from './chat'
const drawer = ref<boolean>(false)
const noKey = ref<boolean>(true)
const formRef = ref<FormInstance>()
const formData = reactive({
openAIApiKey: ''
})
async function saveKey(formEl: any) {
await formEl.validate((valid) => {
if (valid) {
setOpenAIApiKey(formData.openAIApiKey)
describe.value = '我会保管好的!'
noKey.value = false
}
})
}
interface Chat {
text: string
inversion: boolean
}
const chatHistory = ref<Chat[]>([])
const inputM = ref<string>('')
const messageLoading = ref<boolean>(false)
async function handleMessage() {
const request = inputM.value
if (!request) {
describe.value = '聊点什么~'
return
}
inputM.value = ''
chatHistory.value.push({
text: request,
inversion: false
})
messageLoading.value = true
describe.value = '让我想一下...'
const response = await qaChat(request)
describe.value = '聊点什么~'
chatHistory.value.push({
text: response,
inversion: true
})
messageLoading.value = false
}
function handleEnter(event: KeyboardEvent) {
if (event.key === 'Enter' && event.ctrlKey) {
event.preventDefault()
handleMessage()
}
}
</script>

<template>
<el-button :icon="DArrowLeft" style="position: fixed;bottom: 100px;right: 0;border-radius: 40px 0 0 40px;"
@click="drawer = true">
chat
</el-button>
<el-drawer v-model="drawer" direction="rtl" size="40%" center :show-close="false">
<template #header>
<p>{{describe}}</p>
</template>
<template #default>
<div v-if="!chatStore.memoStore">
<el-form v-if="noKey" ref="formRef" :model="formData" label-width="0px" status-icon>
<el-form-item prop="openAIApiKey" :rules="[{ required: true, min: 50, message: '请输入key', trigger: 'blur' }]">
<div class="flex w-full">
<el-input v-model="formData.openAIApiKey" placeholder="请输入Openai Key">
</el-input>
<el-button type="primary" @click="saveKey(formRef)" style="margin-left: 12px;">
确定
</el-button>
</div>
</el-form-item>
</el-form>
<el-button v-else :icon="Switch" type="primary" @click="handleInit" :loading="memoLoading">memo load</el-button>
</div>
<div v-else class="h-full overflow-hidden overflow-y-auto">
<Text v-for="chat in chatHistory" :key="chat.text" :inversion="chat.inversion" :text="chat.text" />
</div>
</template>
<template #footer v-if="!noKey">
<div style="display: flex;">
<el-input placeholder="请输入" v-model="inputM" @@keypress="handleEnter">
</el-input>
<el-button :icon="Promotion" @click="handleMessage" :loading="messageLoading" type="primary" style="margin-left: 12px;"></el-button>
</div>
</template>
</el-drawer>
</template>

<style src="element-plus/dist/index.css" />
3 changes: 3 additions & 0 deletions contents/bot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ref } from 'vue'

export const describe = ref<string>('你好呀')
Loading

0 comments on commit 07a73f0

Please sign in to comment.