Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93d4fb48e7 | |||
| 9dc3711875 | |||
| a671fc91c6 | |||
| d47c20ec51 | |||
| 780e03af38 | |||
| 5d33e55537 | |||
| 84b6985dc2 | |||
| b4f528139c | |||
| 8229879db8 | |||
| 7015e7f4de | |||
| 03c6b44fa2 | |||
| 3af3fdbc9c | |||
| 6dc4bb58ea | |||
| bd2b843e5d | |||
| 5b05723e93 | |||
| 22ad935299 |
+40
-80
@@ -2,24 +2,38 @@ name: Docker Build and Push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- staging
|
||||
tags:
|
||||
- 'v*'
|
||||
paths:
|
||||
- '**.go'
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
- 'Dockerfile'
|
||||
- 'Dockerfile.*'
|
||||
- '.dockerignore'
|
||||
- '.gitea/workflows/build.yml'
|
||||
|
||||
jobs:
|
||||
build-and-push-branches:
|
||||
test:
|
||||
name: Run Tests
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref_type == 'branch'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: 'stable'
|
||||
cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Run go vet
|
||||
run: go vet ./...
|
||||
|
||||
- name: Run tests
|
||||
run: go test -v -p 4 ./...
|
||||
|
||||
|
||||
build-and-push:
|
||||
name: Build and Push Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -28,64 +42,7 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: git.fossy.my.id
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Set version variables
|
||||
id: vars
|
||||
run: |
|
||||
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
|
||||
echo "VERSION=dev-main" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "VERSION=dev-staging" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
|
||||
echo "COMMIT=${{ github.sha }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and push Docker image for main
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
VERSION=${{ steps.vars.outputs.VERSION }}
|
||||
BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }}
|
||||
COMMIT=${{ steps.vars.outputs.COMMIT }}
|
||||
if: github.ref == 'refs/heads/main'
|
||||
|
||||
- name: Build and push Docker image for staging
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:staging
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
VERSION=${{ steps.vars.outputs.VERSION }}
|
||||
BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }}
|
||||
COMMIT=${{ steps.vars.outputs.COMMIT }}
|
||||
if: github.ref == 'refs/heads/staging'
|
||||
|
||||
build-and-push-tags:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: git.fossy.my.id
|
||||
@@ -103,32 +60,35 @@ jobs:
|
||||
if echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
|
||||
MAJOR=$(echo "$VERSION" | cut -d. -f1)
|
||||
MINOR=$(echo "$VERSION" | cut -d. -f2)
|
||||
|
||||
PATCH=$(echo "$VERSION" | cut -d. -f3 | cut -d- -f1)
|
||||
|
||||
echo "MAJOR=$MAJOR" >> $GITHUB_OUTPUT
|
||||
echo "MINOR=$MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "PATCH=$PATCH" >> $GITHUB_OUTPUT
|
||||
|
||||
if echo "$VERSION" | grep -q '-'; then
|
||||
PRERELEASE_TAG=$(echo "$VERSION" | cut -d- -f2 | cut -d. -f1)
|
||||
echo "IS_PRERELEASE=true" >> $GITHUB_OUTPUT
|
||||
echo "ADDITIONAL_TAG=staging" >> $GITHUB_OUTPUT
|
||||
echo "PRERELEASE_TAG=$PRERELEASE_TAG" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT
|
||||
echo "ADDITIONAL_TAG=latest" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
else
|
||||
echo "Invalid version format: $VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build and push Docker image for release
|
||||
- name: Build and push Docker image (release)
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.VERSION }}
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:release
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.MAJOR }}.${{ steps.version.outputs.MINOR }}
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.MAJOR }}
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:${{ steps.version.outputs.ADDITIONAL_TAG }}
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
VERSION=${{ steps.version.outputs.VERSION }}
|
||||
@@ -136,17 +96,17 @@ jobs:
|
||||
COMMIT=${{ steps.version.outputs.COMMIT }}
|
||||
if: steps.version.outputs.IS_PRERELEASE == 'false'
|
||||
|
||||
- name: Build and push Docker image for pre-release
|
||||
- name: Build and push Docker image (pre-release)
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.VERSION }}
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:${{ steps.version.outputs.ADDITIONAL_TAG }}
|
||||
git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:staging
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
VERSION=${{ steps.version.outputs.VERSION }}
|
||||
BUILD_DATE=${{ steps.version.outputs.BUILD_DATE }}
|
||||
COMMIT=${{ steps.version.outputs.COMMIT }}
|
||||
if: steps.version.outputs.IS_PRERELEASE == 'true'
|
||||
if: steps.version.outputs.IS_PRERELEASE == 'true'
|
||||
@@ -1,7 +1,9 @@
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- main
|
||||
- staging
|
||||
- 'feat/**'
|
||||
|
||||
name: SonarQube Scan
|
||||
jobs:
|
||||
@@ -17,7 +19,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.25.6'
|
||||
go-version: 'stable'
|
||||
cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -28,13 +30,13 @@ jobs:
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: |
|
||||
go test ./... -v -coverprofile=coverage
|
||||
go test ./... -v -p 4 -coverprofile=coverage
|
||||
|
||||
- name: Run GolangCI-Lint Analysis
|
||||
uses: golangci/golangci-lint-action@v9
|
||||
with:
|
||||
skip-cache: true
|
||||
version: v2.6
|
||||
version: latest
|
||||
args: >
|
||||
--issues-exit-code=0
|
||||
--output.text.path=stdout
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Run Tests
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'pull_request' ||
|
||||
(github.event_name == 'issue_comment' &&
|
||||
github.event.issue.pull_request != null &&
|
||||
contains(github.event.comment.body, '/retest'))
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: 'stable'
|
||||
cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Run go vet
|
||||
run: go vet ./...
|
||||
|
||||
- name: Run tests
|
||||
run: go test -v -p 4 ./...
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.25.6-alpine AS go_builder
|
||||
FROM golang:1.26.0-alpine AS go_builder
|
||||
|
||||
ARG VERSION=dev
|
||||
ARG BUILD_DATE=unknown
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
module tunnel_pls
|
||||
|
||||
go 1.25.5
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
charm.land/bubbletea/v2 v2.0.0
|
||||
git.fossy.my.id/bagas/tunnel-please-grpc v1.5.0
|
||||
github.com/caddyserver/certmagic v0.25.1
|
||||
github.com/charmbracelet/bubbles v0.21.0
|
||||
github.com/charmbracelet/bubbletea v1.3.10
|
||||
github.com/charmbracelet/bubbles v1.0.0
|
||||
github.com/charmbracelet/lipgloss v1.1.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/libdns/cloudflare v0.2.2
|
||||
github.com/muesli/termenv v0.16.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
golang.org/x/crypto v0.47.0
|
||||
golang.org/x/crypto v0.48.0
|
||||
google.golang.org/grpc v1.78.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
)
|
||||
@@ -21,13 +21,17 @@ require (
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/caddyserver/zerossl v0.1.4 // indirect
|
||||
github.com/charmbracelet/bubbletea v1.3.10 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.4.1 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.11.3 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.14 // indirect
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.11.6 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.6.2 // indirect
|
||||
github.com/charmbracelet/x/termios v0.1.1 // indirect
|
||||
github.com/charmbracelet/x/windows v0.2.2 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.9.0 // indirect
|
||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
@@ -49,12 +53,12 @@ require (
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
golang.org/x/mod v0.31.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/mod v0.32.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
golang.org/x/tools v0.40.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/tools v0.41.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,38 +1,45 @@
|
||||
charm.land/bubbletea/v2 v2.0.0 h1:p0d6CtWyJXJ9GfzMpUUqbP/XUUhhlk06+vCKWmox1wQ=
|
||||
charm.land/bubbletea/v2 v2.0.0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ=
|
||||
git.fossy.my.id/bagas/tunnel-please-grpc v1.5.0 h1:3xszIhck4wo9CoeRq9vnkar4PhY7kz9QrR30qj2XszA=
|
||||
git.fossy.my.id/bagas/tunnel-please-grpc v1.5.0/go.mod h1:Weh6ZujgWmT8XxD3Qba7sJ6r5eyUMB9XSWynqdyOoLo=
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
|
||||
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
|
||||
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
|
||||
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
|
||||
github.com/caddyserver/certmagic v0.25.1 h1:4sIKKbOt5pg6+sL7tEwymE1x2bj6CHr80da1CRRIPbY=
|
||||
github.com/caddyserver/certmagic v0.25.1/go.mod h1:VhyvndxtVton/Fo/wKhRoC46Rbw1fmjvQ3GjHYSQTEY=
|
||||
github.com/caddyserver/zerossl v0.1.4 h1:CVJOE3MZeFisCERZjkxIcsqIH4fnFdlYWnPYeFtBHRw=
|
||||
github.com/caddyserver/zerossl v0.1.4/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
|
||||
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
|
||||
github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc=
|
||||
github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E=
|
||||
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
||||
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
||||
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
|
||||
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
|
||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||
github.com/charmbracelet/x/ansi v0.11.3 h1:6DcVaqWI82BBVM/atTyq6yBoRLZFBsnoDoX9GCu2YOI=
|
||||
github.com/charmbracelet/x/ansi v0.11.3/go.mod h1:yI7Zslym9tCJcedxz5+WBq+eUGMJT0bM06Fqy1/Y4dI=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98=
|
||||
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
|
||||
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241212170349-ad4b7ae0f25f h1:UytXHv0UxnsDFmL/7Z9Q5SBYPwSuRLXHbwx+6LycZ2w=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241212170349-ad4b7ae0f25f/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||
github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo=
|
||||
github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
|
||||
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
|
||||
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
|
||||
github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
|
||||
github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
|
||||
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
|
||||
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
|
||||
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
|
||||
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
|
||||
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
@@ -81,16 +88,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
@@ -121,26 +120,26 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
|
||||
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
|
||||
@@ -151,6 +150,5 @@ google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBN
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -3,14 +3,14 @@ package interaction
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
func (m *model) comingSoonUpdate(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
func (m *model) comingSoonUpdate(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
|
||||
_ = msg
|
||||
m.showingComingSoon = false
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *model) comingSoonView() string {
|
||||
|
||||
@@ -4,9 +4,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
@@ -17,24 +16,22 @@ func (m *model) handleCommandSelection(item commandItem) (tea.Model, tea.Cmd) {
|
||||
m.editingSlug = true
|
||||
m.slugInput.SetValue(m.interaction.slug.String())
|
||||
m.slugInput.Focus()
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
case "tunnel-type":
|
||||
m.showingCommands = false
|
||||
m.showingComingSoon = true
|
||||
return m, tea.Batch(tickCmd(5*time.Second), tea.ClearScreen, textinput.Blink)
|
||||
return m, tickCmd(5 * time.Second)
|
||||
default:
|
||||
m.showingCommands = false
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m *model) commandsUpdate(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
func (m *model) commandsUpdate(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
|
||||
switch {
|
||||
case key.Matches(msg, m.keymap.quit), msg.String() == "esc":
|
||||
m.showingCommands = false
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
case msg.String() == "enter":
|
||||
selectedItem := m.commandList.SelectedItem()
|
||||
if selectedItem != nil {
|
||||
@@ -42,8 +39,8 @@ func (m *model) commandsUpdate(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
return m.handleCommandSelection(item)
|
||||
}
|
||||
}
|
||||
m.commandList, cmd = m.commandList.Update(msg)
|
||||
return m, cmd
|
||||
m.commandList, _ = m.commandList.Update(msg)
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *model) commandsView() string {
|
||||
|
||||
@@ -4,20 +4,19 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
func (m *model) dashboardUpdate(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
func (m *model) dashboardUpdate(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
|
||||
switch {
|
||||
case key.Matches(msg, m.keymap.quit):
|
||||
m.quitting = true
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink, tea.Quit)
|
||||
return m, tea.Quit
|
||||
case key.Matches(msg, m.keymap.command):
|
||||
m.showingCommands = true
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
"tunnel_pls/session/slug"
|
||||
"tunnel_pls/types"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/charmbracelet/bubbles/help"
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/muesli/termenv"
|
||||
"golang.org/x/crypto/ssh"
|
||||
@@ -120,7 +120,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tickMsg:
|
||||
m.showingComingSoon = false
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
@@ -137,9 +137,9 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
|
||||
case tea.QuitMsg:
|
||||
m.quitting = true
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink, tea.Quit)
|
||||
return m, tea.Quit
|
||||
|
||||
case tea.KeyMsg:
|
||||
case tea.KeyPressMsg:
|
||||
if m.showingComingSoon {
|
||||
return m.comingSoonUpdate(msg)
|
||||
}
|
||||
@@ -160,28 +160,28 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
|
||||
func (i *interaction) Redraw() {
|
||||
if i.program != nil {
|
||||
i.program.Send(tea.ClearScreen())
|
||||
i.program.Send(tea.WindowSizeMsg{})
|
||||
}
|
||||
}
|
||||
|
||||
func (m *model) View() string {
|
||||
func (m *model) View() tea.View {
|
||||
var content string
|
||||
if m.quitting {
|
||||
return ""
|
||||
content = ""
|
||||
} else if m.showingComingSoon {
|
||||
content = m.comingSoonView()
|
||||
} else if m.editingSlug {
|
||||
content = m.slugView()
|
||||
} else if m.showingCommands {
|
||||
content = m.commandsView()
|
||||
} else {
|
||||
content = m.dashboardView()
|
||||
}
|
||||
|
||||
if m.showingComingSoon {
|
||||
return m.comingSoonView()
|
||||
}
|
||||
|
||||
if m.editingSlug {
|
||||
return m.slugView()
|
||||
}
|
||||
|
||||
if m.showingCommands {
|
||||
return m.commandsView()
|
||||
}
|
||||
|
||||
return m.dashboardView()
|
||||
v := tea.NewView(content)
|
||||
v.AltScreen = true
|
||||
v.MouseMode = tea.MouseModeCellMotion
|
||||
return v
|
||||
}
|
||||
|
||||
func (i *interaction) Start() {
|
||||
@@ -249,8 +249,6 @@ func (i *interaction) Start() {
|
||||
m,
|
||||
tea.WithInput(i.channel),
|
||||
tea.WithOutput(i.channel),
|
||||
tea.WithAltScreen(),
|
||||
tea.WithMouseCellMotion(),
|
||||
tea.WithoutSignals(),
|
||||
tea.WithoutSignalHandler(),
|
||||
tea.WithFPS(30),
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"time"
|
||||
"tunnel_pls/types"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"golang.org/x/crypto/ssh"
|
||||
@@ -694,7 +694,7 @@ func TestInteraction_Integration(t *testing.T) {
|
||||
func TestModel_Update_KeyMessages(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
key tea.KeyMsg
|
||||
key tea.KeyPressMsg
|
||||
showingComingSoon bool
|
||||
editingSlug bool
|
||||
showingCommands bool
|
||||
@@ -702,25 +702,25 @@ func TestModel_Update_KeyMessages(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "key press while showing coming soon",
|
||||
key: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
key: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
showingComingSoon: true,
|
||||
description: "should call comingSoonUpdate",
|
||||
},
|
||||
{
|
||||
name: "key press while editing slug",
|
||||
key: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
key: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
editingSlug: true,
|
||||
description: "should call slugUpdate",
|
||||
},
|
||||
{
|
||||
name: "key press while showing commands",
|
||||
key: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
key: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
showingCommands: true,
|
||||
description: "should call commandsUpdate",
|
||||
},
|
||||
{
|
||||
name: "key press in dashboard view",
|
||||
key: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'c'}},
|
||||
key: tea.KeyPressMsg{Code: 'c', Text: "c"},
|
||||
description: "should call dashboardUpdate",
|
||||
},
|
||||
}
|
||||
@@ -777,7 +777,7 @@ func TestModel_SlugUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
tunnelType types.TunnelType
|
||||
keyMsg tea.KeyMsg
|
||||
keyMsg tea.KeyPressMsg
|
||||
inputValue string
|
||||
setupMocks func(*MockSessionRegistry, *MockSlug, *MockRandom)
|
||||
expectedEdit bool
|
||||
@@ -787,21 +787,21 @@ func TestModel_SlugUpdate(t *testing.T) {
|
||||
{
|
||||
name: "escape key cancels editing",
|
||||
tunnelType: types.TunnelTypeHTTP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEsc},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEsc},
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {},
|
||||
expectedEdit: false,
|
||||
},
|
||||
{
|
||||
name: "ctrl+c cancels editing",
|
||||
tunnelType: types.TunnelTypeHTTP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyCtrlC},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'c', Mod: tea.ModCtrl},
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {},
|
||||
expectedEdit: false,
|
||||
},
|
||||
{
|
||||
name: "enter key saves valid slug",
|
||||
tunnelType: types.TunnelTypeHTTP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
inputValue: "my-custom-slug",
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {
|
||||
ms.On("String").Return("old-slug")
|
||||
@@ -816,7 +816,7 @@ func TestModel_SlugUpdate(t *testing.T) {
|
||||
{
|
||||
name: "enter key with error shows error message",
|
||||
tunnelType: types.TunnelTypeHTTP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
inputValue: "invalid",
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {
|
||||
ms.On("String").Return("old-slug")
|
||||
@@ -831,7 +831,7 @@ func TestModel_SlugUpdate(t *testing.T) {
|
||||
{
|
||||
name: "ctrl+r generates random slug",
|
||||
tunnelType: types.TunnelTypeHTTP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyCtrlR},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'r', Mod: tea.ModCtrl},
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {
|
||||
mr.On("String", 20).Return("random-generated-slug", nil)
|
||||
},
|
||||
@@ -841,7 +841,7 @@ func TestModel_SlugUpdate(t *testing.T) {
|
||||
{
|
||||
name: "ctrl+r with error does nothing",
|
||||
tunnelType: types.TunnelTypeHTTP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyCtrlR},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'r', Mod: tea.ModCtrl},
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {
|
||||
mr.On("String", 20).Return("", assert.AnError)
|
||||
},
|
||||
@@ -850,14 +850,14 @@ func TestModel_SlugUpdate(t *testing.T) {
|
||||
{
|
||||
name: "regular key updates input",
|
||||
tunnelType: types.TunnelTypeHTTP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'a'}},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'a', Text: "a"},
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {},
|
||||
expectedEdit: true,
|
||||
},
|
||||
{
|
||||
name: "tcp tunnel exits editing immediately",
|
||||
tunnelType: types.TunnelTypeTCP,
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'a'}},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'a', Text: "a"},
|
||||
setupMocks: func(msr *MockSessionRegistry, ms *MockSlug, mr *MockRandom) {},
|
||||
expectedEdit: false,
|
||||
},
|
||||
@@ -1006,19 +1006,19 @@ func TestModel_SlugView(t *testing.T) {
|
||||
func TestModel_ComingSoonUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
keyMsg tea.KeyMsg
|
||||
keyMsg tea.KeyPressMsg
|
||||
}{
|
||||
{
|
||||
name: "any key dismisses coming soon",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
},
|
||||
{
|
||||
name: "escape key dismisses",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEsc},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEsc},
|
||||
},
|
||||
{
|
||||
name: "space key dismisses",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeySpace},
|
||||
keyMsg: tea.KeyPressMsg{Code: ' ', Text: " "},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1097,7 +1097,7 @@ func TestModel_ComingSoonView(t *testing.T) {
|
||||
func TestModel_CommandsUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
keyMsg tea.KeyMsg
|
||||
keyMsg tea.KeyPressMsg
|
||||
selectedItem list.Item
|
||||
expectCommands bool
|
||||
expectEditSlug bool
|
||||
@@ -1105,31 +1105,31 @@ func TestModel_CommandsUpdate(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "escape key closes commands",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEsc},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEsc},
|
||||
expectCommands: false,
|
||||
},
|
||||
{
|
||||
name: "q key closes commands",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'q'}},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'q', Text: "q"},
|
||||
expectCommands: false,
|
||||
},
|
||||
{
|
||||
name: "enter on slug command starts editing",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
selectedItem: commandItem{name: "slug", desc: "Set custom subdomain"},
|
||||
expectCommands: false,
|
||||
expectEditSlug: true,
|
||||
},
|
||||
{
|
||||
name: "enter on tunnel-type shows coming soon",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyEnter},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyEnter},
|
||||
selectedItem: commandItem{name: "tunnel-type", desc: "Change tunnel type"},
|
||||
expectCommands: false,
|
||||
expectComingSoon: true,
|
||||
},
|
||||
{
|
||||
name: "arrow key navigates list",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyDown},
|
||||
keyMsg: tea.KeyPressMsg{Code: tea.KeyDown},
|
||||
expectCommands: true,
|
||||
},
|
||||
}
|
||||
@@ -1261,28 +1261,28 @@ func TestModel_CommandsView(t *testing.T) {
|
||||
func TestModel_DashboardUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
keyMsg tea.KeyMsg
|
||||
keyMsg tea.KeyPressMsg
|
||||
expectQuit bool
|
||||
expectCommands bool
|
||||
}{
|
||||
{
|
||||
name: "q key quits",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'q'}},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'q', Text: "q"},
|
||||
expectQuit: true,
|
||||
},
|
||||
{
|
||||
name: "ctrl+c quits",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyCtrlC},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'c', Mod: tea.ModCtrl},
|
||||
expectQuit: true,
|
||||
},
|
||||
{
|
||||
name: "c key opens commands",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'c'}},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'c', Text: "c"},
|
||||
expectCommands: true,
|
||||
},
|
||||
{
|
||||
name: "other keys do nothing",
|
||||
keyMsg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'x'}},
|
||||
keyMsg: tea.KeyPressMsg{Code: 'x', Text: "x"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
"tunnel_pls/internal/random"
|
||||
"tunnel_pls/types"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/charmbracelet/bubbles/help"
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type commandItem struct {
|
||||
@@ -77,7 +77,7 @@ type keymap struct {
|
||||
type tickMsg time.Time
|
||||
|
||||
func (m *model) Init() tea.Cmd {
|
||||
return tea.Batch(textinput.Blink, tea.WindowSize())
|
||||
return tea.RequestWindowSize
|
||||
}
|
||||
|
||||
func getResponsiveWidth(screenWidth, padding, minWidth, maxWidth int) int {
|
||||
|
||||
@@ -5,26 +5,24 @@ import (
|
||||
"strings"
|
||||
"tunnel_pls/types"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
func (m *model) slugUpdate(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
func (m *model) slugUpdate(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
|
||||
|
||||
if m.tunnelType != types.TunnelTypeHTTP {
|
||||
m.editingSlug = false
|
||||
m.slugError = ""
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
}
|
||||
|
||||
switch msg.String() {
|
||||
case "esc", "ctrl+c":
|
||||
m.editingSlug = false
|
||||
m.slugError = ""
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
case "enter":
|
||||
inputValue := m.slugInput.Value()
|
||||
if err := m.interaction.sessionRegistry.Update(m.interaction.user, types.SessionKey{
|
||||
@@ -39,18 +37,18 @@ func (m *model) slugUpdate(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
m.editingSlug = false
|
||||
m.slugError = ""
|
||||
return m, tea.Batch(tea.ClearScreen, textinput.Blink)
|
||||
return m, nil
|
||||
default:
|
||||
if key.Matches(msg, m.keymap.random) {
|
||||
newSubdomain, err := m.randomizer.String(20)
|
||||
if err != nil {
|
||||
return m, cmd
|
||||
return m, nil
|
||||
}
|
||||
m.slugInput.SetValue(newSubdomain)
|
||||
}
|
||||
m.slugError = ""
|
||||
m.slugInput, cmd = m.slugInput.Update(msg)
|
||||
return m, cmd
|
||||
m.slugInput, _ = m.slugInput.Update(msg)
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user