Skip to content

Latest commit

 

History

History
272 lines (185 loc) · 7.75 KB

File metadata and controls

272 lines (185 loc) · 7.75 KB

Architecture

Overview

Yarrand is a simple Android wrapper application that provides a native mobile experience for the Yarr RSS reader web application. The architecture is intentionally minimal, focusing on a single WebView with essential native features.

Architecture Pattern

The app follows a simplified MVC pattern:

  • Model: YarrandPreferences - manages app settings and preferences
  • View: XML layouts and Android UI components
  • Controller: MainActivity and SettingsActivity - handle user interactions and coordinate between model and view

Components

1. MainActivity

Purpose: Main screen that displays the Yarr web interface

Responsibilities:

  • Initialize and configure WebView
  • Handle navigation (back button)
  • Manage toolbar and menu actions
    • Implement feed refresh via Yarr API and status polling (no pull-to-refresh gesture)
  • Monitor page loading progress
  • Enforce security constraints (URL filtering)

Key Features:

  • YarrandWebViewClient: Custom WebViewClient to handle page loading and navigation
  • YarrandWebChromeClient: Custom WebChromeClient to show progress and page titles
  • Back button override to navigate within SPA instead of closing app

2. SettingsActivity

Purpose: Configuration screen for app settings

Responsibilities:

  • Display and edit server URL
  • Toggle persistent authentication (Keep me logged in)
  • Allow self-signed certificates (for localhost / trusted dev servers)
  • Validate user input
  • Persist settings
  • Provide connection testing

Validation:

  • URL must start with http:// or https://
  • URL cannot be empty
  • Trailing slashes are automatically removed

3. YarrandPreferences

Purpose: Centralized preferences management

Responsibilities:

  • Read/write app settings using SharedPreferences
  • Provide type-safe access to configuration values
  • Handle default values

Stored Settings:

  • server_url: The Yarr server URL
  • dark_mode: Boolean flag for forced dark mode

Data Flow

User Action → Activity → YarrandPreferences → SharedPreferences
                ↓
            WebView (loads Yarr)

Startup Flow

  1. App launches → MainActivity.onCreate()
  2. Load preferences via YarrandPreferences
  3. Check if server URL is configured
  4. If not configured → Show SettingsActivity
  5. If configured → Load URL in WebView
  6. WebView renders Yarr interface
  7. Enable cookie persistence for session management

Settings Flow

  1. User opens Settings from menu
  2. SettingsActivity loads current preferences
  3. User modifies settings
  4. Validation on save
  5. If valid → Save to SharedPreferences
  6. Return to MainActivity
  7. MainActivity checks if URL changed
  8. If changed → Reload WebView

Navigation Flow

  1. User presses back button
  2. MainActivity.onBackPressed() called
  3. Check if WebView.canGoBack()
  4. If true → WebView.goBack()
  5. If false → Exit app (super.onBackPressed())

WebView Configuration

JavaScript & Storage

javaScriptEnabled = true         // Required for modern web apps
domStorageEnabled = true         // LocalStorage support
databaseEnabled = true           // IndexedDB support

Caching

cacheMode = WebSettings.LOAD_DEFAULT  // Standard HTTP cache

Security

allowFileAccess = false          // Prevent file:// URLs
allowContentAccess = false       // Prevent content:// URLs
mixedContentMode = MIXED_CONTENT_COMPATIBILITY_MODE

Feed refresh and JS integration

Feed refresh is implemented by POSTing to /api/feeds/refresh and then polling /api/status. The app injects a small JavaScript helper to start the refresh and monitor status. When the running value reaches 0 the WebView reloads to display updated feeds.

The back navigation handler uses JavaScript injection to detect the SPA view (article / articles list / feeds) and programmatically clicks the appropriate in-page back button so the Android back gesture maps to in-app navigation.

Cookie Management

CookieManager.setAcceptCookie(true)
CookieManager.setAcceptThirdPartyCookies(webView, true)

Cookies are persisted to support the "Keep me logged in" setting. When enabled the app calls CookieManager.flush() during lifecycle pause to persist cookies; when disabled the app clears cookies on startup.

Security Considerations

URL Filtering

  • Only allows navigation within the configured Yarr server
  • External links are blocked and show a toast message
  • Prevents unintended navigation to malicious sites

HTTPS

  • HTTPS is recommended for production
  • HTTP is allowed for local development/testing
  • Cleartext traffic enabled in manifest for local servers

Additional behaviour:

  • The app includes a setting to allow self-signed TLS certificates for localhost/trusted dev servers. This option is disabled by default and limited to localhost, 127.0.0.1 or the configured server host. If disabled, WebView will cancel loads on SSL errors.

No JavaScript Interfaces

  • No @JavascriptInterface methods exposed
  • Prevents potential XSS attacks from web content

Resource Structure

res/
├── layout/
│   ├── activity_main.xml        # Main screen with WebView
│   └── activity_settings.xml    # Settings screen
├── menu/
│   └── main_menu.xml            # Toolbar menu items
├── values/
│   ├── strings.xml              # All user-facing strings
│   ├── colors.xml               # App color palette
│   └── themes.xml               # Material Design theme
└── mipmap/                      # App launcher icons

Build Configuration

Gradle Modules

  • Root project: Configuration and plugin versions
  • app module: Application code and resources

Key Dependencies

  • AndroidX: Core Android libraries
  • Material Components: UI components following Material Design
  • WebKit: Advanced WebView features
  • SwipeRefreshLayout: Pull-to-refresh gesture

Build Variants

  • Debug: No minification, debugging enabled
  • Release: ProGuard enabled, optimized

Testing Strategy (Planned)

Unit Tests

  • YarrandPreferences - preferences management
  • URL validation logic
  • Dark mode detection

Instrumented Tests

  • WebView initialization
  • Navigation flow
  • Settings persistence

UI Tests

  • Settings screen interactions
  • Menu actions
  • Back button behavior

Performance Considerations

WebView Lifecycle

  • Properly pause/resume WebView with activity lifecycle
  • Destroy WebView in onDestroy to prevent memory leaks

Progress Indication

  • Horizontal progress bar for page loading
  • Swipe refresh indicator
  • Both automatically hidden when loading completes

Memory Management

  • Single WebView instance per activity
  • No WebView caching across activities
  • Cookies persisted via CookieManager, not in-memory

Future Enhancements

Potential Improvements

  1. Service Worker Support: Enable for offline caching
  2. JavaScript Bridge: Add interface for native features (share, notifications)
  3. Multiple Profiles: Support multiple Yarr servers
  4. Background Sync: Periodic feed checking with notifications
  5. Custom User Agent: Identify as Yarrand for server-side customization

Architecture Evolution

As features grow, consider:

  • ViewModel + LiveData: For settings management
  • Repository Pattern: For data access abstraction
  • Dependency Injection: Using Hilt for testability
  • Navigation Component: For multi-screen flows

Code Style

  • Language: Kotlin
  • Naming: camelCase for variables/functions, PascalCase for classes
  • Comments: Document non-obvious behavior
  • String Resources: All user-facing text in strings.xml
  • Null Safety: Leverage Kotlin's null safety features

License

MIT License - See LICENSE file for details