diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 6b4d3d8..7223bfe 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -39,7 +39,10 @@ "WebFetch(domain:getstream.io)", "WebFetch(domain:blog.logrocket.com)", "WebFetch(domain:virtuoso.dev)", - "WebFetch(domain:medium.com)" + "WebFetch(domain:medium.com)", + "Bash(keytool:*)", + "Bash(echo:*)", + "Bash(python -c \"import base64; print\\(base64.b64encode\\(open\\(r''C:\\\\Users\\\\bryan\\\\Desktop\\\\Discord Clone\\\\discord-clone-release.keystore'',''rb''\\).read\\(\\)\\).decode\\(\\)\\)\")" ] } } diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index cba6412..78a0beb 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -90,6 +90,36 @@ jobs: VITE_LIVEKIT_URL: ${{ secrets.VITE_LIVEKIT_URL }} CUSTOM_APP_BUILDER_PATH: /tmp/app-builder + - name: Decode Android keystore + run: | + echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > /tmp/discord-clone-release.keystore + echo "ANDROID_KEYSTORE_FILE=/tmp/discord-clone-release.keystore" >> $GITHUB_ENV + echo "ANDROID_KEYSTORE_PASSWORD=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}" >> $GITHUB_ENV + echo "ANDROID_KEY_ALIAS=${{ secrets.ANDROID_KEY_ALIAS }}" >> $GITHUB_ENV + echo "ANDROID_KEY_PASSWORD=${{ secrets.ANDROID_KEY_PASSWORD }}" >> $GITHUB_ENV + + - name: Build web app for Android + run: npm run build -w apps/web + env: + VITE_CONVEX_URL: ${{ secrets.VITE_CONVEX_URL }} + VITE_LIVEKIT_URL: ${{ secrets.VITE_LIVEKIT_URL }} + + - name: Capacitor sync + run: npx cap sync + working-directory: apps/android + + - name: Build Android APK + run: | + cd apps/android/android + chmod +x gradlew + ./gradlew assembleRelease --no-daemon + + - name: Copy APK to dist + run: | + VERSION="${{ steps.version.outputs.version }}" + cp apps/android/android/app/build/outputs/apk/release/app-release.apk \ + apps/electron/dist/DiscordClone-v${VERSION}.apk + - name: List build artifacts run: ls -la apps/electron/dist/ @@ -126,7 +156,8 @@ jobs: apps/electron/dist/*.exe \ apps/electron/dist/*.exe.blockmap \ apps/electron/dist/*.AppImage \ - apps/electron/dist/*.flatpak; do + apps/electron/dist/*.flatpak \ + apps/electron/dist/*.apk; do [ -f "$file" ] || continue FILENAME=$(basename "$file") ENCODED_NAME=$(echo -n "$FILENAME" | jq -sRr @uri) diff --git a/TODO.md b/TODO.md index f9b101b..dcb7ccd 100644 --- a/TODO.md +++ b/TODO.md @@ -7,10 +7,16 @@ - Add photo / video albums like Commit https://commet.chat/ - - +- Are we using the encryped sql database to help load messages faster? -- Are we using the encryped sql database to help load messages faster? \ No newline at end of file +- Notification on taskbar for windows +- Notification popup for windows for discord + + + +# Android + +- On android lets make sure we can save the user login like we do on electron so they dont have to login everytime. + +- On android why does my app not reach the bottom of the screen that its allowed? \ No newline at end of file diff --git a/apps/android/package.json b/apps/android/package.json index 26079a9..5d33616 100644 --- a/apps/android/package.json +++ b/apps/android/package.json @@ -1,7 +1,7 @@ { "name": "@discord-clone/android", "private": true, - "version": "1.0.0", + "version": "1.0.25", "type": "module", "scripts": { "cap:sync": "npx cap sync", diff --git a/apps/electron/package.json b/apps/electron/package.json index d4e2110..9e8d272 100644 --- a/apps/electron/package.json +++ b/apps/electron/package.json @@ -1,7 +1,7 @@ { "name": "@discord-clone/electron", "private": true, - "version": "1.0.24", + "version": "1.0.25", "description": "Discord Clone - Electron app", "author": "Moyettes", "type": "module", diff --git a/apps/web/package.json b/apps/web/package.json index 9bf8fff..23c6c1d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,7 +1,7 @@ { "name": "@discord-clone/web", "private": true, - "version": "1.0.0", + "version": "1.0.25", "type": "module", "scripts": { "dev": "vite", diff --git a/livekit.yaml b/livekit.yaml index 5ffe363..7d1acc5 100644 --- a/livekit.yaml +++ b/livekit.yaml @@ -14,6 +14,8 @@ rtc: port_range_start: 50000 port_range_end: 50100 use_external_ip: false # false for local dev; set true for production + node_ip: 72.26.56.3 # advertise LAN IP so Android/other-network clients can reach + tcp_port: 7881 # ICE-over-TCP fallback (Android emulator blocks UDP high ports) # API credentials (must match LIVEKIT_API_KEY / LIVEKIT_API_SECRET env vars) keys: diff --git a/packages/shared/package.json b/packages/shared/package.json index 60501e0..9998da9 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,7 +1,7 @@ { "name": "@discord-clone/shared", "private": true, - "version": "1.0.24", + "version": "1.0.25", "type": "module", "main": "src/App.jsx", "dependencies": { diff --git a/packages/shared/src/contexts/VoiceContext.jsx b/packages/shared/src/contexts/VoiceContext.jsx index 67843b2..9a5ec68 100644 --- a/packages/shared/src/contexts/VoiceContext.jsx +++ b/packages/shared/src/contexts/VoiceContext.jsx @@ -240,6 +240,17 @@ export const VoiceProvider = ({ children }) => { setConnectionState('connecting'); try { + // Request microphone permission (triggers Android runtime prompt) + try { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + stream.getTracks().forEach(t => t.stop()); + } catch (e) { + console.error('Microphone permission denied:', e); + setConnectionState('error'); + setActiveChannelId(null); + return; + } + const { token: lkToken } = await convex.action(api.voice.getToken, { channelId, userId, @@ -255,10 +266,18 @@ export const VoiceProvider = ({ children }) => { const noiseSuppression = localStorage.getItem('voiceNoiseSuppression') !== 'false'; // default true + const isMobile = /Android|iPhone|iPad/i.test(navigator.userAgent); + const newRoom = new Room({ adaptiveStream: true, dynacast: true, autoSubscribe: true, + rtcConfig: { + iceServers: [ + { urls: 'stun:stun.l.google.com:19302' }, + { urls: 'stun:stun1.l.google.com:19302' }, + ], + }, audioCaptureDefaults: { autoGainControl: true, echoCancellation: true, @@ -275,7 +294,7 @@ export const VoiceProvider = ({ children }) => { dtx: false, red: true, videoEncoding: VideoPresets.h720.encoding, - videoCodec: 'vp9', + videoCodec: isMobile ? 'vp8' : 'vp9', screenShareEncoding: { maxBitrate: 10_000_000, maxFramerate: 60, diff --git a/packages/shared/src/index.css b/packages/shared/src/index.css index 68ed055..dc59796 100644 --- a/packages/shared/src/index.css +++ b/packages/shared/src/index.css @@ -422,7 +422,6 @@ body { .chat-input-form { padding: 0 8px 8px; - margin-top: 24px; background-color: var(--bg-primary); }