Component Overview
MegaDownloader consists of several core components, each with specific responsibilities in the application architecture.
Main Window Manager
Main.java
Location : Main.java:29
Responsibilities :
Application window management
Panel navigation using CardLayout
Media polling service coordination
Custom window dragging for undecorated frame
FlatLaf Darcula theme setup
Panel Management : Manages all application panels (Login, Main, Preferences, Media)
Navigation State : Tracks current and previous panel for back button functionality
Dependency Injection : Connects panels with shared services
Auto-login : Checks for saved credentials on startup
Configuration Check : Validates yt-dlp configuration on launch
Navigation Methods :
public void showMainPanel () {
previousPanel = currentPanel;
currentPanel = "MAIN" ;
cardLayout . show (cardPanel, "MAIN" );
}
public void showPreferencesPanel () {
previousPanel = currentPanel;
currentPanel = "PREFERENCES" ;
cardLayout . show (cardPanel, "PREFERENCES" );
}
public void goBack () {
cardLayout . show (cardPanel, previousPanel);
currentPanel = previousPanel;
}
public void logout () {
loginForm . clearToken ();
showLoginForm ();
}
Window Dragging Implementation (Main.java:139):
private void enableDragging ( Component component) {
component . addMouseListener ( new MouseAdapter () {
@ Override
public void mousePressed ( MouseEvent e ) {
initialClick = e . getPoint ();
}
});
component . addMouseMotionListener ( new MouseMotionAdapter () {
@ Override
public void mouseDragged ( MouseEvent e ) {
int thisX = Main . this . getLocation (). x ;
int thisY = Main . this . getLocation (). y ;
int xMoved = e . getX () - initialClick . x ;
int yMoved = e . getY () - initialClick . y ;
Main . this . setLocation (thisX + xMoved, thisY + yMoved);
}
});
}
The enableDragging() method is applied to the content pane, menu bar, and media polling component to allow window movement.
Download Interface
MainPanel.java
Location : MainPanel.java:30
Responsibilities :
URL input and validation
yt-dlp process execution
Download progress monitoring
Audio/video format selection
Custom arguments support
M3U playlist generation
Integration with FFmpeg for audio extraction
Process Execution : Spawns yt-dlp subprocess with ProcessBuilder
Progress Parsing : Real-time progress bar updates from yt-dlp output
FFmpeg Integration : Auto-detects FFmpeg in yt-dlp directory
Speed Limiting : Applies download speed limits from preferences
Playlist Support : Creates M3U playlists for downloaded media
File Tracking : Opens downloaded files with system default player
Download Process (MainPanel.java:481):
SwingWorker < Integer , Integer > worker = new SwingWorker < Integer , Integer >() {
@ Override
protected Integer doInBackground () throws Exception {
List < String > command = new ArrayList <>();
command . add (ytdlpPath);
if (ffmpegLocation != null ) {
command . add ( "--ffmpeg-location" );
command . add (ffmpegLocation);
}
if (limiterEnabled) {
command . add ( "--limit-rate" );
command . add (speedLimitKBps + "K" );
}
if (audioOnly) {
command . add ( "-x" );
command . add ( "--audio-format" );
command . add ( "mp3" );
}
command . add (url);
ProcessBuilder pb = new ProcessBuilder (command);
Process process = pb . start ();
// Parse output for progress updates
return process . waitFor ();
}
};
Configuration Loading (MainPanel.java:174):
private String getYtDlpPath () {
File configFile = new File ( "config.txt" );
try ( BufferedReader reader = new BufferedReader ( new FileReader (configFile))) {
String line ;
while ((line = reader . readLine ()) != null ) {
if ( line . startsWith ( "path: \" " ) && line . endsWith ( " \" " )) {
return line . substring ( 6 , line . length () - 1 );
}
}
}
return null ;
}
Authentication
Location : LoginForm.java:44
Responsibilities :
User authentication via API
Credential validation (email format, password)
Session persistence with Java Preferences API
Auto-login on startup
Token management
Email Validation : Real-time regex-based email validation
Visual Feedback : Red border on invalid input
Remember Me : Stores credentials using Preferences API
Auto-login : Validates saved tokens on startup
API Integration : Uses MediaPollingComponent for authentication
Email Validation (LoginForm.java:176):
private boolean validateEmail () {
String email = txtEmail . getText ();
Pattern pattern = Pattern . compile ( "^[ \\ w.-]+@[ \\ w.-]+ \\ .[a-zA-Z]{2,}$" );
if ( ! pattern . matcher (email). matches ()) {
txtEmail . setBorder ( BorderFactory . createLineBorder ( new Color ( 220 , 53 , 69 )));
return false ;
}
txtEmail . setBorder (defaultBorder);
return true ;
}
Token Persistence (LoginForm.java:247):
private void saveToken ( String email, String token) {
prefs . put ( "auth_token" , token);
prefs . put ( "user_email" , email);
}
public boolean checkAutoLogin () {
String savedToken = prefs . get ( "auth_token" , null );
String savedEmail = prefs . get ( "user_email" , null );
if (savedToken != null && savedEmail != null ) {
if ( mediaPollingComponent . checkToken (savedToken)) {
this . token = savedToken;
mediaPollingComponent . setToken (savedToken);
return true ;
} else {
clearToken ();
}
}
return false ;
}
Location : ManageMediaPanel.java:39
Responsibilities :
Display local and server media files
Search and filter functionality
File operations (play, delete, download)
Server synchronization
Quick actions context menu
Dual Source Display : Shows both local and server files in one table
Real-time Filtering : Text search and type filtering (Video/Audio/All)
Quick Actions : Context menu and action list for common operations
Download Indicator : Shows download status with symbols (✓, ⬇, ✗)
Live Updates : Listens for new media from MediaPollingComponent
Media Loading (ManageMediaPanel.java:76):
private void loadMediaFiles () {
File directory = new File (currentDirectory);
List < File > mediaFiles = getMediaFiles (directory);
List < Media > serverMedia = getMediaFromNetwork ();
DefaultTableModel model = (DefaultTableModel) tblFiles . getModel ();
model . setRowCount ( 0 );
// Add local files with server sync status
for ( File file : mediaFiles) {
DownloadedMedia media = new DownloadedMedia ( file . getAbsolutePath ());
boolean existsOnServer = serverMedia . stream ()
. anyMatch (serverItem -> media . matchesServerMedia (serverItem));
String status = existsOnServer ? "✓" : "" ;
String source = existsOnServer ? "Both" : "Local" ;
model . addRow ( new Object []{
status, media . getFileName (), media . getMediaType (),
formatFileSize ( media . getFileSize ()), media . getDate (), source
});
}
// Add server-only files
for ( Media serverItem : serverMedia) {
boolean existsLocally = mediaList . stream ()
. anyMatch (localMedia -> localMedia . matchesServerMedia (serverItem));
if ( ! existsLocally) {
model . addRow ( new Object []{
"" , serverItem . mediaFileName ,
getMediaTypeFromMime ( serverItem . mediaMimeType ),
"" , "" , "Server"
});
}
}
}
Live Media Updates (ManageMediaPanel.java:771):
mediaPollingComponent . addMediaPollingListener (newMedia -> {
SwingUtilities . invokeLater (() -> {
mediaFromServer . addAll (newMedia);
addNewMediaToTable (newMedia);
});
});
Settings Configuration
PreferencesPanel.java
Location : PreferencesPanel.java:33
Responsibilities :
yt-dlp path configuration
Download directory selection
FFmpeg path configuration
Speed limiter settings
M3U playlist generation toggle
Configuration persistence
File Choosers : JFileChooser for selecting executables and directories
Speed Limiter : Slider and text field synchronized controls (1-100000 KB/s)
Config Persistence : Saves settings to config.txt
Validation : Ensures paths are configured before saving
Configuration Saving (PreferencesPanel.java:345):
private void btnSaveActionPerformed ( java . awt . event . ActionEvent evt) {
String path = lblYtdlpCurrentPath . getText ();
String downloadDirectoryPath = lblDownloadDirectoryPath . getText ();
if ( path . equals ( "Not configured" )) {
JOptionPane . showMessageDialog ( this ,
"Please select a yt-dlp location first" );
return ;
}
try ( BufferedWriter writer = new BufferedWriter (
new FileWriter ( "config.txt" ))) {
writer . write ( "path: \" " + path + " \" " );
writer . newLine ();
if ( ! downloadDirectoryPath . equals ( "Default (where project is stored)" )) {
writer . write ( "downloadDir: \" " + downloadDirectoryPath + " \" " );
}
JOptionPane . showMessageDialog ( this ,
"Configuration saved successfully!" );
}
}
About Dialog
AboutDialog.java
Location : AboutDialog.java:14
Responsibilities :
Display application information
Show version and author details
Display application logo and banner
Modal dialog with ESC key to close
Image Loading (AboutDialog.java:47):
private void loadBannerImage () {
java . net . URL imageURL = getClass (). getResource ( "/images/YTDLPBanner.png" );
ImageIcon originalIcon = new ImageIcon (imageURL);
// Scale image to fit label while maintaining aspect ratio
double scaleX = ( double ) labelWidth / originalWidth;
double scaleY = ( double ) labelHeight / originalHeight;
double scale = Math . min (scaleX, scaleY);
Image scaledImage = originalIcon . getImage ()
. getScaledInstance (scaledWidth, scaledHeight, Image . SCALE_SMOOTH );
lblPhoto . setIcon ( new ImageIcon (scaledImage));
}
Data Model
Location : DownloadedMedia.java:21
Responsibilities :
Represent downloaded media files
Extract file metadata (size, date, MIME type)
Match local files with server media
File deletion operations
MIME Detection : Uses Files.probeContentType() to detect file type
Server Matching : Compares local files with server media by ID, GUID, or filename
Metadata Extraction : Reads file size, modification date, and type
File Operations : Delete functionality with validation
Server Media Matching (DownloadedMedia.java:114):
public boolean matchesServerMedia ( Media serverMedia) {
// Match by server ID if known
if ( this . serverId != null && this . serverId == serverMedia . id ) {
return true ;
}
// Match by blob GUID
if ( this . serverBlobGuid != null &&
this . serverBlobGuid . equals ( serverMedia . blobNameGuid )) {
return true ;
}
// Match by filename and MIME type
return this . fileName . equals ( serverMedia . mediaFileName ) &&
this . mimeType . equals ( serverMedia . mediaMimeType );
}
MIME Type Detection (DownloadedMedia.java:66):
private String detectMimeType ( File file) {
try {
String mimeType = Files . probeContentType ( file . toPath ());
if (mimeType != null ) {
return mimeType;
}
} catch ( IOException ex ) {
// Log error
}
return "unknown" ;
}
Component Relationships
Dependency Graph
Data Flow
Authentication Flow : LoginForm → MediaPollingComponent → API → Token Storage
Download Flow : MainPanel → Config → yt-dlp Process → File System
Media Management Flow : ManageMediaPanel → Local Files + Server API → Table Display
Configuration Flow : PreferencesPanel → config.txt → All Panels
All long-running operations (authentication, downloads, API calls) use SwingWorker to prevent UI freezing.