Skip to content

Commit 533379b

Browse files
Merge branch 'stage' into ADFA-1414-tooltips-for-operators
2 parents 2e1efb1 + 0975600 commit 533379b

File tree

523 files changed

+13568
-34661
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

523 files changed

+13568
-34661
lines changed

.github/workflows/debug.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ jobs:
7676
timeout-minutes: 60
7777
needs: check_changes
7878
if: needs.check_changes.outputs.must_build == 'true'
79+
env:
80+
SKIP_LLAMA_ASSETS: "true"
7981

8082
steps:
8183

.github/workflows/release.yml

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ permissions:
88
on:
99
schedule:
1010
- cron: '0 12 * * *' # Daily at 12:00 PM UTC
11-
workflow_dispatch: #
11+
workflow_dispatch:
1212

1313
env:
1414
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -582,60 +582,16 @@ jobs:
582582
583583
echo "FIREBASE_CONSOLE_URL=$FIREBASE_URL" >> $GITHUB_OUTPUT
584584
585-
- name: Set up SSH key
585+
- name: Install uv
586+
uses: astral-sh/setup-uv@v6
587+
588+
- name: Upload APK to Cloudflare R2
586589
env:
587-
GREENGEEKS_HOST: ${{ vars.GREENGEEKS_SSH_HOST }}
588-
GREENGEEKS_KEY: ${{ secrets.GREENGEEKS_SSH_PRIVATE_KEY }}
589-
GREENGEEKS_USER: ${{ vars.GREENGEEKS_SSH_USER }}
590+
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
591+
CLOUDFLARE_KEY_ID: ${{ vars.CLOUDFLARE_KEY_ID }}
592+
CLOUDFLARE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_SECRET_ACCESS_KEY }}
590593
run: |
591-
mkdir -p ~/.ssh
592-
if [ -z "$GREENGEEKS_HOST" ]; then
593-
echo "Error: SSH_HOST variable is not set"
594-
exit 1
595-
fi
596-
# Write the SSH key, ensuring proper formatting
597-
echo "$GREENGEEKS_KEY" > ~/.ssh/id_rsa
598-
# Remove any trailing newlines and ensure proper key format
599-
sed -i '' -e '$ { /^$/ d; }' ~/.ssh/id_rsa 2>/dev/null || sed -i '$ { /^$/ d; }' ~/.ssh/id_rsa
600-
chmod 600 ~/.ssh/id_rsa
601-
# Verify key format
602-
if ! grep -q "BEGIN.*PRIVATE KEY" ~/.ssh/id_rsa; then
603-
echo "Error: SSH key does not appear to be in correct format"
604-
exit 1
605-
fi
606-
# Configure SSH to use only the key file and disable other auth methods
607-
cat > ~/.ssh/config <<EOF
608-
Host *
609-
IdentitiesOnly yes
610-
PreferredAuthentications publickey
611-
StrictHostKeyChecking no
612-
UserKnownHostsFile ~/.ssh/known_hosts
613-
PubkeyAuthentication yes
614-
PasswordAuthentication no
615-
ChallengeResponseAuthentication no
616-
GSSAPIAuthentication no
617-
GSSAPIKeyExchange no
618-
GSSAPIDelegateCredentials no
619-
Host $GREENGEEKS_HOST
620-
User $GREENGEEKS_USER
621-
IdentityFile ~/.ssh/id_rsa
622-
IdentitiesOnly yes
623-
PreferredAuthentications publickey
624-
PubkeyAuthentication yes
625-
PasswordAuthentication no
626-
ChallengeResponseAuthentication no
627-
GSSAPIAuthentication no
628-
GSSAPIKeyExchange no
629-
GSSAPIDelegateCredentials no
630-
NumberOfPasswordPrompts 0
631-
EOF
632-
chmod 600 ~/.ssh/config
633-
# Disable SSH agent completely
634-
unset SSH_AUTH_SOCK
635-
unset SSH_AGENT_PID
636-
# Remove any default SSH keys that might interfere
637-
rm -f ~/.ssh/id_ed25519 ~/.ssh/id_ecdsa ~/.ssh/id_dsa ~/.ssh/id_rsa.pub 2>/dev/null
638-
ssh-keyscan -H "$GREENGEEKS_HOST" >> ~/.ssh/known_hosts 2>/dev/null
594+
uv run --with boto3 scripts/cloudflare-r2-upload.py "${{ steps.find_apk.outputs.APK_PATH }}"
639595
640596
- name: Clean up build folder after upload
641597
run: |
@@ -735,8 +691,26 @@ jobs:
735691
736692
rm -f payload.json
737693
694+
- name: Send Telegram message
695+
env:
696+
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
697+
TELEGRAM_EARLY_ACCESS_CHAT_ID: ${{ vars.TELEGRAM_EARLY_ACCESS_CHAT_ID }}
698+
APK_PATH: ${{ steps.find_apk.outputs.APK_PATH }}
699+
run: |
700+
GIT_LOG=$(git log --oneline --since "24 hours ago" || true)
701+
if [ -z "$GIT_LOG" ]; then
702+
GIT_LOG="(no commits in the last 24 hours)"
703+
fi
704+
APK_FILENAME=$(basename "$APK_PATH")
705+
DOWNLOAD_URL="https://download.appdevforall.org/${APK_FILENAME}"
706+
MESSAGE=$(printf "Download: %s\n\n%s" "$DOWNLOAD_URL" "$GIT_LOG")
707+
MESSAGE="${MESSAGE:0:4096}"
708+
curl -s -X POST -H "Content-Type: application/json" \
709+
-d "$(jq -n --arg chat_id "$TELEGRAM_EARLY_ACCESS_CHAT_ID" --arg text "$MESSAGE" '{chat_id: $chat_id, text: $text}')" \
710+
"https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage"
711+
738712
- name: Cleanup google-services.json
739713
if: always()
740714
run: |
741715
rm -f app/google-services.json
742-
echo "google-services.json cleaned up successfully"
716+
echo "google-services.json cleaned up successfully"

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<h2 align="center"><b>Code On The Go</b></h2>
66
<p align="center">
7-
Code on the Go is an IDE that lets you build Android apps on Android phones, without needing a traditional computer or Internet access.</p>
7+
Code on the Go is an IDE that lets you build Android apps on Android phones, without needing a traditional computer or Internet access. Code on the Go is a project of App Dev for All, a nonprofit organization committed to making computer science education and professional programming resources universally available.</p>
88
<p><br>
99

1010
<p align="center">
@@ -104,3 +104,4 @@ along with Code On The Go. If not, see <https://www.gnu.org/licenses/>.
104104
Any violations to the license can be reported either by opening an issue or writing a mail to us
105105
directly.
106106

107+

actions/src/main/java/com/itsaky/androidide/actions/ActionItem.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,10 @@ interface ActionItem {
209209
EDITOR_FILE_TREE("ide.editor.fileTree"),
210210

211211
/** Location marker for action items shown in UI Designer activity's toolbar. */
212-
UI_DESIGNER_TOOLBAR("ide.uidesigner.toolbar");
212+
UI_DESIGNER_TOOLBAR("ide.uidesigner.toolbar"),
213+
214+
/** Location marker for action items shown on the main screen. */
215+
MAIN_SCREEN("ide.main.screen");
213216

214217
override fun toString(): String {
215218
return id

apk-viewer-plugin/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ android {
3535
jvmTarget = "17"
3636
}
3737

38+
39+
3840
packaging {
3941
resources {
4042
excludes += setOf(

apk-viewer-plugin/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<application
55
android:label="APK Viewer"
6-
android:theme="@style/Theme.AppCompat">
6+
android:theme="@style/PluginTheme">
77

88
<!-- Plugin metadata -->
99
<meta-data
@@ -16,7 +16,7 @@
1616

1717
<meta-data
1818
android:name="plugin.version"
19-
android:value="1.0.1" />
19+
android:value="${pluginVersion}" />
2020

2121
<meta-data
2222
android:name="plugin.description"

apk-viewer-plugin/src/main/kotlin/com/example/sampleplugin/ApkViewer.kt

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,25 @@ import com.itsaky.androidide.plugins.extensions.MenuItem
99
import com.itsaky.androidide.plugins.extensions.TabItem
1010
import com.itsaky.androidide.plugins.extensions.EditorTabItem
1111
import com.itsaky.androidide.plugins.extensions.NavigationItem
12+
import com.itsaky.androidide.plugins.extensions.FileOpenExtension
13+
import com.itsaky.androidide.plugins.extensions.FileTabMenuItem
1214
import com.itsaky.androidide.plugins.services.IdeEditorTabService
15+
import com.example.sampleplugin.R
1316
import com.example.sampleplugin.fragments.ApkAnalyzerFragment
17+
import java.io.File
1418

1519
/**
1620
* APK Viewer Plugin
1721
* Provides APK analysis functionality via main menu toolbar and bottom sheet
1822
*/
19-
class ApkViewer : IPlugin, UIExtension, EditorTabExtension {
23+
class ApkViewer : IPlugin, UIExtension, EditorTabExtension, FileOpenExtension {
2024

2125
private lateinit var context: PluginContext
26+
private var pendingAnalysisFile: File? = null
27+
28+
companion object {
29+
private const val TAB_ID = "apk_analyzer_main_tab"
30+
}
2231

2332
override fun initialize(context: PluginContext): Boolean {
2433
return try {
@@ -86,7 +95,7 @@ class ApkViewer : IPlugin, UIExtension, EditorTabExtension {
8695
NavigationItem(
8796
id = "apk_analyzer_sidebar",
8897
title = "APK Analyzer",
89-
icon = android.R.drawable.ic_menu_info_details,
98+
icon = R.drawable.ic_apk_analyzer,
9099
isEnabled = true,
91100
isVisible = true,
92101
group = "tools",
@@ -101,9 +110,9 @@ class ApkViewer : IPlugin, UIExtension, EditorTabExtension {
101110
return listOf(
102111

103112
EditorTabItem(
104-
id = "apk_analyzer_main_tab",
113+
id = TAB_ID,
105114
title = "APK Analyzer",
106-
icon = android.R.drawable.ic_menu_info_details,
115+
icon = R.drawable.ic_apk_analyzer,
107116
fragmentFactory = {
108117
context.logger.debug("Creating ApkAnalyzerFragment")
109118
ApkAnalyzerFragment()
@@ -120,6 +129,11 @@ class ApkViewer : IPlugin, UIExtension, EditorTabExtension {
120129

121130
override fun onEditorTabSelected(tabId: String, fragment: Fragment) {
122131
context.logger.info("Editor tab selected: $tabId")
132+
val file = pendingAnalysisFile ?: return
133+
pendingAnalysisFile = null
134+
if (tabId == TAB_ID && fragment is ApkAnalyzerFragment) {
135+
fragment.analyzeFile(file)
136+
}
123137
}
124138

125139
override fun onEditorTabClosed(tabId: String) {
@@ -130,6 +144,44 @@ class ApkViewer : IPlugin, UIExtension, EditorTabExtension {
130144
return true
131145
}
132146

147+
override fun canHandleFileOpen(file: File): Boolean {
148+
return file.extension.equals("apk", ignoreCase = true)
149+
}
150+
151+
override fun handleFileOpen(file: File): Boolean {
152+
pendingAnalysisFile = file
153+
openApkAnalyzerTab()
154+
return true
155+
}
156+
157+
override fun onFileOpened(file: File) {
158+
if (file.extension.equals("apk", ignoreCase = true)) {
159+
context.logger.info("APK file opened: ${file.name}")
160+
}
161+
}
162+
163+
override fun getFileTabMenuItems(file: File): List<FileTabMenuItem> {
164+
if (!file.extension.equals("apk", ignoreCase = true)) return emptyList()
165+
166+
return listOf(
167+
FileTabMenuItem(
168+
id = "apk_viewer.analyze",
169+
title = "Analyze APK",
170+
order = 0,
171+
action = {
172+
pendingAnalysisFile = file
173+
openApkAnalyzerTab()
174+
}
175+
)
176+
)
177+
}
178+
179+
override fun onFileClosed(file: File) {
180+
if (file.extension.equals("apk", ignoreCase = true)) {
181+
context.logger.info("APK file closed: ${file.name}")
182+
}
183+
}
184+
133185
private fun openApkAnalyzerTab() {
134186
context.logger.info("Opening APK Analyzer tab")
135187

@@ -145,7 +197,7 @@ class ApkViewer : IPlugin, UIExtension, EditorTabExtension {
145197
}
146198

147199
try {
148-
if (editorTabService.selectPluginTab("apk_analyzer_main_tab")) {
200+
if (editorTabService.selectPluginTab(TAB_ID)) {
149201
context.logger.info("Successfully opened APK Analyzer tab")
150202
} else {
151203
context.logger.warn("Failed to open APK Analyzer tab")

0 commit comments

Comments
 (0)