diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 17409a3..a0090ca 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -13,14 +13,14 @@ env:
jobs:
build:
- runs-on: [self-hosted,FlipperZeroShell]
+ runs-on: ubuntu-latest
steps:
- name: 'Checkout code'
uses: actions/checkout@v3
with:
fetch-depth: 0
- - name: 'Set image tag'
+ - name: 'Set image tag and name'
id: tag
run: |
IMAGE_TAG="0.0.0"
@@ -31,6 +31,7 @@ jobs:
fi
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
+ echo "image_name=${IMAGE_NAME}" >> $GITHUB_OUTPUT
- name: 'Login to Docker Hub'
uses: docker/login-action@v2
@@ -39,17 +40,36 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- - name: 'Build docker image'
- run: |
- docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" .
+ - name: 'Set up Docker Buildx'
+ uses: docker/setup-buildx-action@v2
+
+ - name: 'Build and push dev'
+ if: ${{ steps.tag.outputs.image_tag == '0.0.0' }}
+ id: docker_build_dev
+ uses: docker/build-push-action@v4
+ with:
+ push: true
+ tags: ${{steps.tag.outputs.image_name}}:${{steps.tag.outputs.image_tag}}
+ file: Dockerfile-dev
+
+ - name: 'Build and push prod'
+ if: ${{ steps.tag.outputs.image_tag != '0.0.0' }}
+ id: docker_build_prod
+ uses: docker/build-push-action@v4
+ with:
+ push: true
+ tags: ${{steps.tag.outputs.image_name}}:${{steps.tag.outputs.image_tag}}
+ file: Dockerfile-prod
- - name: 'Upload docker image'
+ - name: 'Show dev image digest'
+ if: ${{ steps.tag.outputs.image_tag == '0.0.0' }}
run: |
- docker push "$IMAGE_NAME:$IMAGE_TAG"
+ echo ${{ steps.docker_build_dev.outputs.digest }}
- - name: 'Show image digest'
+ - name: 'Show prod image digest'
+ if: ${{ steps.tag.outputs.image_tag != '0.0.0' }}
run: |
- docker image inspect --format='{{index .RepoDigests 0}}' "$IMAGE_NAME:$IMAGE_TAG" | awk -F '@' '{print $2}'
+ echo ${{ steps.docker_build_prod.outputs.digest }}
- name: 'Trigger k8s to use new image'
uses: peter-evans/repository-dispatch@v2
diff --git a/.gitignore b/.gitignore
index 553e134..f64d6b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,10 @@
.DS_Store
.thumbs.db
-node_modules
+frontend/node_modules
# Quasar core related directories
-.quasar
-/dist
-
-# Cordova related directories and files
-/src-cordova/node_modules
-/src-cordova/platforms
-/src-cordova/plugins
-/src-cordova/www
-
-# Capacitor related directories and files
-/src-capacitor/www
-/src-capacitor/node_modules
-
-# BEX related directories and files
-/src-bex/www
-/src-bex/js/core
+frontend/.quasar
+frontend/dist
# Log files
npm-debug.log*
diff --git a/Dockerfile b/Dockerfile-dev
similarity index 83%
rename from Dockerfile
rename to Dockerfile-dev
index 25a2fb3..15c9b61 100644
--- a/Dockerfile
+++ b/Dockerfile-dev
@@ -7,8 +7,7 @@ COPY frontend/package.json frontend/package-lock.json ./
RUN npm install
COPY frontend/ .
-RUN quasar build -m spa
-
+RUN npm run build/dev
FROM alpine
@@ -18,4 +17,4 @@ COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=frontend /app/dist/spa /usr/share/nginx/html
EXPOSE 80
-ENTRYPOINT ["nginx", "-g", "daemon off;"]
\ No newline at end of file
+ENTRYPOINT ["nginx", "-g", "daemon off;"]
diff --git a/Dockerfile-prod b/Dockerfile-prod
new file mode 100644
index 0000000..d16a9f7
--- /dev/null
+++ b/Dockerfile-prod
@@ -0,0 +1,20 @@
+FROM node:16-alpine as frontend
+WORKDIR /app
+
+RUN npm install -g @quasar/cli
+
+COPY frontend/package.json frontend/package-lock.json ./
+RUN npm install
+
+COPY frontend/ .
+RUN npm run build
+
+FROM alpine
+
+RUN apk update && apk add tzdata nginx
+
+COPY nginx.conf /etc/nginx/nginx.conf
+COPY --from=frontend /app/dist/spa /usr/share/nginx/html
+
+EXPOSE 80
+ENTRYPOINT ["nginx", "-g", "daemon off;"]
diff --git a/frontend/src/components/AppList.vue b/frontend/src/components/AppList.vue
index 9d6b71b..30d5ab1 100644
--- a/frontend/src/components/AppList.vue
+++ b/frontend/src/components/AppList.vue
@@ -58,8 +58,8 @@
-
-
{{ app.currentVersion.name }}
+
+
{{ app.currentVersion.name }}
diff --git a/frontend/src/components/InstalledApps.vue b/frontend/src/components/InstalledApps.vue
index ed36482..d3cf859 100644
--- a/frontend/src/components/InstalledApps.vue
+++ b/frontend/src/components/InstalledApps.vue
@@ -49,7 +49,7 @@
{{ app.currentVersion.name }}
-
{{ app.currentVersion.shortDescription }}
+
{{ app.currentVersion.shortDescription }}
@@ -113,7 +113,7 @@
{{ app.currentVersion.name }}
-
{{ app.currentVersion.shortDescription }}
+
{{ app.currentVersion.shortDescription }}
diff --git a/frontend/src/css/app.sass b/frontend/src/css/app.sass
index 24538d7..23034e0 100644
--- a/frontend/src/css/app.sass
+++ b/frontend/src/css/app.sass
@@ -147,3 +147,12 @@ body
padding: 0.5rem 0
font-weight: 500
margin: 0.5rem 0 0.75rem
+
+// Dialogs
+.dialog
+ border-radius: 20px
+ padding: 16px
+ .dialog-close-btn
+ position: absolute
+ top: 0.5rem
+ right: 0.5rem
diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue
index d791572..a9b8e98 100644
--- a/frontend/src/layouts/MainLayout.vue
+++ b/frontend/src/layouts/MainLayout.vue
@@ -321,6 +321,27 @@
+
+
+
+
+
+
+
+ Can't connect to Flipper
+ It seems that the serial port is occupied. Close any other app (e.g. qFlipper) connected to Flipper and try again.
+
+
+
+
+
+
+
@@ -360,6 +381,7 @@ export default defineComponent({
installFromFile: false,
logsPopup: false,
settingsView: false,
+ flipperOccupiedDialog: false,
catalogCanBeEnabled: false,
catalogCanSwitchChannel: false,
@@ -496,6 +518,7 @@ export default defineComponent({
this.flags.portSelectRequired = false
this.connectionStatus = 'Flipper connected'
this.flags.connected = true
+ this.flags.flipperOccupiedDialog = false
this.log({
level: 'info',
message: `${this.componentName}: Flipper connected`
@@ -507,7 +530,14 @@ export default defineComponent({
.catch((error) => {
if (error.toString() === 'Error: No known ports') {
this.flags.portSelectRequired = true
+ } else if (error.toString().includes('Failed to open serial port')) {
+ this.flags.portSelectRequired = true
+ this.flags.flipperOccupiedDialog = true
} else {
+ this.log({
+ level: 'error',
+ message: `${this.componentName}: Failed to connect: ${error}`
+ })
this.connectionStatus = error.toString()
}
})
@@ -543,6 +573,9 @@ export default defineComponent({
},
async startRpc () {
+ if (!this.flags.connected) {
+ return
+ }
this.flags.rpcToggling = true
await this.flipper.startRPCSession()
.catch(error => {
@@ -572,6 +605,9 @@ export default defineComponent({
},
async readInfo () {
+ if (!this.flags.connected) {
+ return
+ }
this.info = {
doneReading: false,
storage: {
@@ -652,6 +688,9 @@ export default defineComponent({
},
async setTime () {
+ if (!this.flags.connected) {
+ return
+ }
await this.flipper.RPC('systemSetDatetime', { date: new Date() })
.catch(error => this.rpcErrorHandler(error, 'systemSetDatetime'))
.finally(() => {
@@ -858,28 +897,25 @@ export default defineComponent({
if (localStorage.getItem('installFromFile') === 'true') {
this.flags.installFromFile = true
}
- if (localStorage.getItem('catalogChannel') && localStorage.getItem('catalogChannel') !== 'production') {
- this.flags.catalogChannelProduction = false
- }
- if (localStorage.getItem('catalogEnabled') === 'true') {
- this.flags.catalogEnabled = true
- }
- if (!process.env.PRODUCTION) {
- this.flags.catalogCanSwitchChannel = true
- }
- // FIXME
- if (location.host === 'lab.flipper.net') {
- this.flags.catalogCanSwitchChannel = false
- this.flags.catalogChannelProduction = true
- localStorage.setItem('catalogChannel', 'production')
- } else if (location.host === 'lab.flipp.dev') {
- this.flags.catalogCanSwitchChannel = false
- if (!localStorage.getItem('catalogChannel')) {
+ const isProd = process.env.PRODUCTION
+ const savedChannel = localStorage.getItem('catalogChannel')
+ if (savedChannel) {
+ if (savedChannel !== 'production') {
this.flags.catalogChannelProduction = false
- this.toggleCatalogChannel()
+ } else {
+ this.flags.catalogCanSwitchChannel = true
+ }
+ } else {
+ if (isProd) {
+ localStorage.setItem('catalogChannel', 'production')
+ } else {
+ localStorage.setItem('catalogChannel', 'dev')
+ this.flags.catalogChannelProduction = false
+ this.flags.catalogCanSwitchChannel = true
}
}
+
navigator.serial.addEventListener('disconnect', e => {
this.autoReconnect()
})
diff --git a/frontend/src/pages/Apps.vue b/frontend/src/pages/Apps.vue
index eb01582..f83e891 100644
--- a/frontend/src/pages/Apps.vue
+++ b/frontend/src/pages/Apps.vue
@@ -318,6 +318,7 @@ export default defineComponent({
watch: {
flipperReady () {
+ this.flags.connectFlipperDialog = false
this.start()
},
@@ -933,13 +934,4 @@ export default defineComponent({
font-size: 10px
border: 1px #ffffff solid
border-radius: 17px
-
-// Dialogs
-.dialog
- border-radius: 20px
- padding: 16px
-.dialog-close-btn
- position: absolute
- top: 0.5rem
- right: 0.5rem
diff --git a/frontend/src/util/util.js b/frontend/src/util/util.js
index 53d88c6..8e9b810 100644
--- a/frontend/src/util/util.js
+++ b/frontend/src/util/util.js
@@ -7,7 +7,7 @@ let API_ENDPOINT = process.env.ARCHIVARIUS_API_ENDPOINT
if (localStorage.getItem('catalogChannel') !== null) {
if (localStorage.getItem('catalogChannel') === 'production') {
API_ENDPOINT = 'https://catalog.flipperzero.one/api/v0'
- } else if (localStorage.getItem('catalogChannel') === 'dev') {
+ } else {
API_ENDPOINT = 'https://catalog.flipp.dev/api/v0'
}
}