Skip to content

Latest commit

Β 

History

51 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Flukavike

An iOS client for Fluxer β€” a modern messaging platform that is a competitor to Discord.

Join the TestFlight Beta β†’


Known Issues

Voice channels, camera view, and microphone mute syncing with the Fluxer backend are now working. Server profile images, GIFs, and @mentions are also fixed.

No known issues at this time β€” report anything via Settings β†’ Contact Support.

Design Guidelines

This project follows these design principles:

  • Polished & Refined: Every pixel matters, smooth 120fps animations
  • Playful but Professional: Delightful micro-interactions without being childish
  • Customizable: Multiple themes (Light, Dark, OLED Dark, Sandstone, Ocean, Forest, Solarized) with 11 accent colors
  • Content First: Clean typography, generous whitespace
  • Native Feel: Built with SwiftUI for optimal performance

Features

Implemented

Feature Description
Theme System Light, Dark, OLED Dark, Sandstone, Ocean, Forest, Solarized modes with 11 accent colors
App Lock Biometric (Face ID / Touch ID) + PIN protection for app data
Accessibility Increase Contrast toggle for improved legibility
Home Shell Sidebar navigation with DMs, Favorites, and Guilds sections
Chat Interface Message bubbles, reactions, voice messages, rich attachments, inline replies
GIF Support Pick and send GIFs via the system document picker
Quick Switcher Cmd-K switcher to jump between channels and DMs instantly
Navigation Customizable tab bar with floating compose button
Notifications Push notifications with mentions, DMs, calls
Voice/Video Calls CallKit native integration for calls
Voice Channels Join voice channels with participant tracking and speaking indicators
Presence Real-time user online/offline/idle status via PresenceStore
Image Caching Efficient async image loading with in-memory cache
Profile User profiles with stats and customization
Settings Comprehensive settings with appearance options
Onboarding Welcome flow with web-based OAuth login
Authentication Secure token storage in Keychain with web OAuth flow
Composer Rich message composer with attachments, GIFs, and voice recording
Search Global search for messages and content
Messages View Dedicated messages/DMs interface
Starred Channels Persistent favorites synced across sessions

Design Highlights

  • Hexagon Branding: Fluxer logo-inspired shapes throughout
  • Inline Replies: Long-press any message to reply
  • Custom Context Menus: Long-press channels/servers for quick actions
  • Toast Notifications WIP: Visual feedback for actions
  • Smooth Animations: Spring-based transitions
  • Haptic Feedback: Tactile responses for interactions
  • Adaptive Colors: Dynamic text and background colors
  • Real-time: WebSocket events for messages, calls, and presence

Project Structure

flukavike/
β”œβ”€β”€ FluxerApp.swift              # App entry point with push setup
β”œβ”€β”€ Services/
β”‚   β”œβ”€β”€ APIService.swift         # Fluxer REST API client
β”‚   β”œβ”€β”€ WebSocketService.swift   # Real-time Gateway connection
β”‚   β”œβ”€β”€ WebAuthService.swift     # Web-based OAuth authentication
β”‚   β”œβ”€β”€ KeychainTokenStore.swift # Secure token storage
β”‚   β”œβ”€β”€ FluxerCallService.swift  # CallKit & voice calls
β”‚   β”œβ”€β”€ AudioRecorderService.swift # Voice message recording
β”‚   β”œβ”€β”€ AudioPlayerService.swift # Voice message playback
β”‚   β”œβ”€β”€ BiometricLockService.swift # App lock (Face ID/Touch ID + PIN)
β”‚   β”œβ”€β”€ PushNotificationService.swift # APNs handling
β”‚   β”œβ”€β”€ UserCache.swift          # In-memory user object cache
β”‚   └── SiriDonationService.swift # Siri intent donation
β”œβ”€β”€ Stores/
β”‚   β”œβ”€β”€ ThemeManager.swift       # Theme & app state management
β”‚   β”œβ”€β”€ ImageCache.swift         # Async image caching
β”‚   β”œβ”€β”€ PresenceStore.swift      # Real-time user presence
β”‚   └── StarredChannelsStore.swift # Persisted starred channels
β”œβ”€β”€ Models/
β”‚   └── Models.swift             # Data models (User, Message, Server, etc.)
β”œβ”€β”€ Views/
β”‚   β”œβ”€β”€ Main/
β”‚   β”‚   β”œβ”€β”€ MainTabView.swift    # Bottom tab navigation
β”‚   β”‚   β”œβ”€β”€ OnboardingView.swift # Welcome & login flow
β”‚   β”‚   β”œβ”€β”€ WebLoginView.swift   # Web-based OAuth login
β”‚   β”‚   └── WebAPILoginView.swift # API-based login fallback
β”‚   β”œβ”€β”€ Home/
β”‚   β”‚   β”œβ”€β”€ HomeShellView.swift  # Sidebar shell (DMs / Favorites / Guilds)
β”‚   β”‚   β”œβ”€β”€ HomeView.swift       # Home dashboard content
β”‚   β”‚   β”œβ”€β”€ GuildNavigationView.swift # Server/guild navigation sidebar
β”‚   β”‚   β”œβ”€β”€ ChannelListView.swift # Channel browser
β”‚   β”‚   └── StarredChannelsView.swift # Starred channels list
β”‚   β”œβ”€β”€ Messages/
β”‚   β”‚   └── MessagesView.swift   # Direct messages view
β”‚   β”œβ”€β”€ Chat/
β”‚   β”‚   └── ChatView.swift       # Message interface with inline replies
β”‚   β”œβ”€β”€ Call/
β”‚   β”‚   β”œβ”€β”€ CallView.swift       # Active call UI
β”‚   β”‚   └── VoiceChannelView.swift # Voice channel grid
β”‚   β”œβ”€β”€ Compose/
β”‚   β”‚   └── ComposeView.swift    # Message composer
β”‚   β”œβ”€β”€ Search/
β”‚   β”‚   └── SearchView.swift     # Global search
β”‚   β”œβ”€β”€ Notifications/
β”‚   β”‚   └── NotificationsView.swift
β”‚   β”œβ”€β”€ Profile/
β”‚   β”‚   └── ProfileView.swift
β”‚   β”œβ”€β”€ Settings/
β”‚   β”‚   β”œβ”€β”€ SettingsView.swift
β”‚   β”‚   └── PinSetupView.swift   # PIN enrollment/change for app lock
β”‚   └── Common/
β”‚       β”œβ”€β”€ CommonViews.swift    # Shared UI components
β”‚       β”œβ”€β”€ AppLockView.swift    # Biometric + PIN lock overlay
β”‚       β”œβ”€β”€ CachedAsyncImage.swift # AsyncImage wrapper with caching
β”‚       β”œβ”€β”€ QuickSwitcherView.swift # Cmd-K channel/DM quick switcher
β”‚       β”œβ”€β”€ GIFDocumentPicker.swift # System GIF file picker
β”‚       β”œβ”€β”€ ContextMenus.swift   # Channel/server/DM context menus
β”‚       └── HCaptchaView.swift   # hCaptcha verification
β”œβ”€β”€ Intents/
β”‚   └── FlukavikeIntents.swift   # Siri intent definitions
└── docs/
    β”œβ”€β”€ DESIGN.md                # Design system documentation
    β”œβ”€β”€ SPEC.md                  # Technical specification
    β”œβ”€β”€ API_REFERENCE.md         # Fluxer API documentation
    β”œβ”€β”€ API_INTEGRATION.md       # Integration guide
    β”œβ”€β”€ SIRI_INTEGRATION.md      # Siri setup guide
    β”œβ”€β”€ PUSH_CALL_SETUP.md       # Push notification setup
    β”œβ”€β”€ PREVIEW.md               # Preview/testing guide
    └── ACCESSIBILITY.md         # Accessibility features

Getting Started

Requirements

  • iOS 26.4
  • Xcode 15.0+
  • Swift 5.9+
  • CocoaPods (for dependencies)

Running the Project

  1. Clone the repository
  2. Run pod install in the project directory
  3. Open flukavike.xcworkspace in Xcode
  4. Select an iOS Simulator or device
  5. Build and run (⌘+R)

Customization

Adding a New Theme

Edit ThemeManager.swift:

enum AppTheme: String, CaseIterable, Identifiable {
    case system = "System"
    case light = "Light"
    case dark = "Dark"
    case oled = "OLED Dark"
    case sandstone = "Sandstone"
    case ocean = "Ocean"
    case forest = "Forest"
    case solarized = "Solarized"
    case yourTheme = "Your Theme" // Add here
}

Adding a New Accent Color

enum AccentColor: String, CaseIterable, Identifiable {
    // ... existing colors
    case yourColor = "Your Color"
    
    var color: Color {
        switch self {
        // ... existing cases
        case .yourColor: return Color(red: ..., green: ..., blue: ...)
        }
    }
}

Screenshots

Home Chat Profile Settings
Server pills, recent conversations Message bubbles, reactions User stats Themes, accent colors

What NOT to touch see below

Critical: Message Decoding β€” Mixed-Type Fluxer Objects

Do not simplify the MessageReference or EmojiObject structs in Models.swift.

Fluxer's API returns two objects that cannot be decoded as [String: String]:

  • message_reference β€” contains a type field with an integer value alongside string fields. Decoding as [String: String] throws a typeMismatch error that propagates up and fails the entire message array, breaking history loading on any channel with replied-to messages.

  • emoji (inside reactions) β€” contains id (integer or null) and animated (bool) alongside the name string. Same consequence: one bad reaction kills the whole channel decode.

Both are handled with private typed structs (MessageReference, EmojiObject) that only decode the fields actually needed, with try? used at the call sites so any unexpected shape produces a nil rather than a throw.

File: Models/Models.swift β€” search for ⚠️ WARNING to find all three affected sites.


Critical: Channel Loading Architecture

Do not change how channels are fetched without reading this first.

Fluxer does not return channel data from the REST endpoint GET /guilds/{id}/channels β€” that endpoint always returns an empty array [] for regular user tokens, regardless of guild membership or permissions.

Channels are delivered exclusively through the WebSocket Gateway READY event, the same pattern Discord uses for large guilds. The READY payload includes a guilds array where each guild object contains its full channel list.

The channel loading flow is:

  1. FluxerApp connects the WebSocket on login
  2. When the Gateway sends READY, onReady stores ready.guilds into AppState.gatewayGuilds
  3. HomeView.loadChannels(for:) checks appState.gatewayGuilds first and uses the channels from there
  4. HomeView has an .onChange(of: appState.gatewayGuilds) observer that reloads channels if the READY event arrives after the initial server list load
  5. The REST call at the bottom of loadChannels is a last-resort fallback only (it will return [] on Fluxer but may work on other compatible instances)

Files involved:

  • FluxerApp.swift β€” webSocketService.onReady callback
  • Stores/ThemeManager.swift β€” AppState.gatewayGuilds
  • Views/Home/HomeView.swift β€” loadChannels(for:) and .onChange(of: appState.gatewayGuilds)

Recent Updates

App Lock (Face ID / Touch ID + PIN)

Full biometric protection with fallback PIN. Lock screen appears on app background/foreground and at launch.

Home Shell Redesign

New sidebar-driven layout with separate sections for DMs, Favorites, and Guilds. Replaces the previous tab-based home screen.

Quick Switcher

Cmd-K (keyboard) or swipe-accessible switcher to jump between any channel or DM without navigating the sidebar.

GIF Support

Attach GIFs directly from the system file picker in the message composer.

Presence Tracking

Real-time online, idle, and offline status for users powered by WebSocket Gateway events.

Image Caching

All avatars and media load via an in-memory cache to eliminate redundant network requests and reduce jank.

Chat Improvements

Overhauled chat view with better message grouping, user caching to avoid repeated API lookups, and smoother scroll behavior.

Voice Channels

Updated voice channel grid with improved speaking indicators and participant tracking.

Starred Channels

Mark channels as favorites for quick access; state persists across sessions.

Toast Notification System

All actions provide visual feedback via toast notifications that appear at the bottom of the screen.


Roadmap

Phase 1: Core (done)

  • Basic UI structure
  • Theme system
  • Navigation
  • Web-based OAuth authentication

Phase 2: Integration (done)

  • Fluxer API client
  • WebSocket connection
  • Real-time messaging
  • Gateway-based channel loading

Phase 3: Polish (mostly done)

  • Push notifications
  • CallKit integration
  • Inline message replies
  • Voice messages
  • Search functionality
  • Toast notification system
  • App Lock (Face ID / Touch ID + PIN)
  • GIF attachment support
  • Quick Switcher (Cmd-K)
  • Image caching
  • User presence tracking
  • Screen sharing
  • Widgets

Phase 4: Advanced (in progress)

  • iPad multi-column support
  • Siri integration
  • Share extension

Documentation


Learning Resources

New to Swift/SwiftUI? Here are some helpful resources:


Contributing

This is a learning project! Feel free to:

  • Fork and experiment
  • Submit improvements
  • Report issues
  • Share your own versions

License

MIT License - feel free to use this as a starting point for your own projects.


Acknowledgments

  • Built for the Fluxer platform
  • Created for educational purposes

Made with SwiftUI

About

a 3rd party mobile client for Fluxer

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages