Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

dot.

Minimal VLESS client for Android with an AMOLED-first, Nothing-inspired interface.

Current Android version: 0.1.8

Features

  • VLESS with REALITY / TLS
  • HTTPS subscription import
  • plaintext and Base64 subscription decoding
  • multiple subscription groups
  • subscription refresh reports with added, edited and deleted node counts/details
  • classified subscription update errors with redacted raw-error viewing while keeping existing nodes intact
  • node selection and persistence
  • per-subscription node sorting by provider order, delay or natural name order
  • delay sorting runs URL tests first when current latency data is unavailable
  • LIST / MAP views for nodes, with LIST as the default
  • interactive world map with real country geometry, borders, Mercator projection, pinch zoom and pan
  • DNS + IP geolocation for subscription nodes with local caching
  • fallback country detection from node flags, ISO codes and country names when IP geolocation fails
  • country-level node grouping so multiple nodes do not overlap on the map
  • node latency / connection tests through libXray URL testing
  • direct node selection and switching while connected
  • Android VpnService + TUN integration
  • libXray / Xray-core backend
  • realtime upload/download traffic
  • foreground VPN notification with active node and traffic
  • Quick Settings connect/disconnect tile
  • long-press Quick Settings tile opens dot.
  • AMOLED, Graphite and Matrix themes
  • selectable launcher icon variants
  • no accounts, ads, analytics or telemetry

Subscription updates

Refreshing a subscription now compares the newly parsed VLESS profiles with the currently stored profiles before replacing them. dot. reports added, edited and deleted nodes, preserves the selected node when the same logical endpoint was edited, and carries matching latency results across the refresh.

If downloading or parsing fails, the previous working node list is retained. The error dialog presents a readable explanation and an optional raw error view; subscription credentials and VLESS user IDs are redacted before raw errors reach the UI.

Node sorting

Sorting is stored independently for each subscription:

  • ORIGIN keeps the exact order received from the provider
  • DELAY orders successful URL-test results from lowest to highest latency, then failed and untested nodes
  • NAME uses natural numeric ordering, so France #2 comes before France #10

Choosing DELAY without current test data starts the existing group URL test first and keeps the list stable until that batch completes. The selected sort mode is also applied to node lists opened from country markers on the map.

Node map

The map is a lightweight custom Compose renderer rather than a full map SDK. It downloads low-resolution country GeoJSON, caches it locally, renders real borders with a dark ProtonVPN-inspired presentation and keeps node markers interactive while zooming and panning.

Node location resolution follows a fallback chain:

  1. resolve the node hostname to a public IP
  2. perform IP geolocation
  3. if that fails, infer the country from the node name using an emoji flag, ISO code or common country name

Only the resolved node IP is sent to the geolocation provider; subscription URLs, UUIDs and VLESS credentials are not included.

Design

dot. intentionally keeps the interface small: pure-black AMOLED surfaces, monospace/Courier-like typography, sharp geometry and pixel-art accents inspired by Nothing OS.

Installation

Development builds are produced by GitHub Actions. Open the latest successful android workflow run and download the dot-debug artifact.

Debug builds use the same development signing key, so newer versions can be installed over previous builds without deleting app data.

Build from source

Requirements:

  • JDK 17
  • Android SDK 36 / Build Tools 36.0.0
  • Gradle 9.5.0

The CI downloads the pinned libXray Android AAR before compilation.

gradle testDebugUnitTest
gradle assembleDebug

APK output:

app/build/outputs/apk/debug/app-debug.apk

Privacy

Treat subscription URLs containing user IDs or tokens as credentials. Do not publish real subscription links, UUIDs or unredacted runtime logs.

Stack

Kotlin · Jetpack Compose · Android VpnService · OkHttp · libXray / Xray-core · GitHub Actions

Documentation

License

A project license has not been selected yet.

Releases

Packages

Contributors

Languages