@@ -8,6 +8,8 @@ import GdkPixbuf from 'gi://GdkPixbuf';
88
99import { extractColorsFromWallpaperIM } from '../utils/imagemagick-color-extraction.js' ;
1010import { adjustColor } from '../utils/color-utils.js' ;
11+ import { uploadWallpaper } from '../utils/wallpaper-utils.js' ;
12+ import { copyFile } from '../utils/file-utils.js' ;
1113import { ColorSwatchGrid } from './palette/color-swatch-grid.js' ;
1214import { ColorPickerDialog } from './palette/color-picker-dialog.js' ;
1315import { WallpaperBrowser } from './WallpaperBrowser.js' ;
@@ -253,8 +255,14 @@ export const PaletteGenerator = GObject.registerClass(
253255 hexpand : true ,
254256 } ) ;
255257
258+ // Empty state - shown when no wallpaper is loaded
259+ this . _emptyStateBox = this . _createEmptyState ( ) ;
260+ viewBox . append ( this . _emptyStateBox ) ;
261+
256262 // Wallpaper selection row - wrapped in PreferencesGroup for full width
257- const wallpaperGroup = new Adw . PreferencesGroup ( ) ;
263+ this . _wallpaperGroup = new Adw . PreferencesGroup ( {
264+ visible : false , // Hidden initially until wallpaper is loaded
265+ } ) ;
258266
259267 const wallpaperRow = new Adw . ActionRow ( {
260268 title : 'Wallpaper' ,
@@ -267,14 +275,6 @@ export const PaletteGenerator = GObject.registerClass(
267275 valign : Gtk . Align . CENTER ,
268276 } ) ;
269277
270- const selectButton = new Gtk . Button ( {
271- icon_name : 'document-open-symbolic' ,
272- valign : Gtk . Align . CENTER ,
273- tooltip_text : 'Select wallpaper' ,
274- } ) ;
275- selectButton . connect ( 'clicked' , ( ) => this . _selectWallpaper ( ) ) ;
276- buttonBox . append ( selectButton ) ;
277-
278278 // ImageMagick extract button
279279 const imExtractButtonBox = new Gtk . Box ( {
280280 orientation : Gtk . Orientation . HORIZONTAL ,
@@ -295,7 +295,6 @@ export const PaletteGenerator = GObject.registerClass(
295295 this . _imExtractButton = new Gtk . Button ( {
296296 child : imExtractButtonBox ,
297297 css_classes : [ 'suggested-action' ] ,
298- visible : false ,
299298 tooltip_text : 'Extract colors from wallpaper' ,
300299 } ) ;
301300 this . _imExtractButton . connect ( 'clicked' , ( ) => {
@@ -326,7 +325,6 @@ export const PaletteGenerator = GObject.registerClass(
326325 child : editButtonBox ,
327326 tooltip_text :
328327 'Edit wallpaper (apply filters before extraction)' ,
329- visible : false ,
330328 } ) ;
331329 this . _editWallpaperBtn . connect ( 'clicked' , ( ) =>
332330 this . _openWallpaperEditor ( )
@@ -368,20 +366,20 @@ export const PaletteGenerator = GObject.registerClass(
368366
369367 wallpaperRow . add_suffix ( buttonBox ) ;
370368
371- this . _setupDropTarget ( wallpaperRow ) ;
372- wallpaperGroup . add ( wallpaperRow ) ;
373- viewBox . append ( wallpaperGroup ) ;
369+ this . _wallpaperGroup . add ( wallpaperRow ) ;
374370
375- // Wallpaper preview
371+ // Wallpaper preview (hidden with wallpaperGroup)
376372 this . _wallpaperPreview = new Gtk . Picture ( {
377373 height_request : 200 ,
378374 can_shrink : true ,
379375 content_fit : Gtk . ContentFit . CONTAIN ,
380376 css_classes : [ 'card' ] ,
381377 hexpand : true ,
382- visible : false ,
378+ visible : false , // Hidden by default, shown when wallpaper loads
383379 } ) ;
384- viewBox . append ( this . _wallpaperPreview ) ;
380+ this . _wallpaperGroup . add ( this . _wallpaperPreview ) ;
381+
382+ viewBox . append ( this . _wallpaperGroup ) ;
385383
386384 // Color swatch grid section
387385 const colorsHeaderBox = new Gtk . Box ( {
@@ -402,7 +400,6 @@ export const PaletteGenerator = GObject.registerClass(
402400 this . _pickFromWallpaperBtn = new Gtk . Button ( {
403401 icon_name : 'color-select-symbolic' ,
404402 tooltip_text : 'Pick colors from wallpaper' ,
405- visible : false ,
406403 } ) ;
407404 this . _pickFromWallpaperBtn . connect ( 'clicked' , ( ) => {
408405 this . _openWallpaperColorPicker ( ) ;
@@ -470,56 +467,69 @@ export const PaletteGenerator = GObject.registerClass(
470467 this . emit ( 'palette-generated' , defaultColors ) ;
471468 }
472469
473- _setupDropTarget ( widget ) {
474- const dropTarget = Gtk . DropTarget . new (
475- Gio . File . $gtype ,
476- Gdk . DragAction . COPY
477- ) ;
470+ _createEmptyState ( ) {
471+ const emptyBox = new Gtk . Box ( {
472+ orientation : Gtk . Orientation . VERTICAL ,
473+ valign : Gtk . Align . CENTER ,
474+ halign : Gtk . Align . CENTER ,
475+ spacing : 24 ,
476+ margin_top : 48 ,
477+ margin_bottom : 48 ,
478+ hexpand : true ,
479+ vexpand : true ,
480+ } ) ;
478481
479- dropTarget . connect ( 'drop' , ( target , value ) => {
480- if ( value instanceof Gio . File ) {
481- this . loadWallpaperWithoutExtraction ( value . get_path ( ) ) ;
482- return true ;
483- }
484- return false ;
482+ const icon = new Gtk . Image ( {
483+ icon_name : 'folder-pictures-symbolic' ,
484+ pixel_size : 72 ,
485+ css_classes : [ 'dim-label' ] ,
485486 } ) ;
486487
487- widget . add_controller ( dropTarget ) ;
488- }
488+ const titleLabel = new Gtk . Label ( {
489+ label : 'No Wallpaper Selected' ,
490+ css_classes : [ 'title-2' ] ,
491+ } ) ;
492+
493+ const subtitleLabel = new Gtk . Label ( {
494+ label : 'Choose a wallpaper to begin creating your theme' ,
495+ css_classes : [ 'dim-label' ] ,
496+ } ) ;
489497
490- _selectWallpaper ( ) {
491- const dialog = new Gtk . FileDialog ( { title : 'Select Wallpaper' } ) ;
498+ const uploadButton = new Gtk . Button ( {
499+ label : 'Select Wallpaper' ,
500+ css_classes : [ 'pill' , 'suggested-action' ] ,
501+ halign : Gtk . Align . CENTER ,
502+ } ) ;
503+ uploadButton . connect ( 'clicked' , ( ) => {
504+ this . _uploadWallpaper ( ) ;
505+ } ) ;
492506
493- const filter = new Gtk . FileFilter ( ) ;
494- filter . add_mime_type ( 'image/png' ) ;
495- filter . add_mime_type ( 'image/jpeg' ) ;
496- filter . add_mime_type ( 'image/webp' ) ;
497- filter . set_name ( 'Images' ) ;
507+ emptyBox . append ( icon ) ;
508+ emptyBox . append ( titleLabel ) ;
509+ emptyBox . append ( subtitleLabel ) ;
510+ emptyBox . append ( uploadButton ) ;
498511
499- const filterList = Gio . ListStore . new ( Gtk . FileFilter . $gtype ) ;
500- filterList . append ( filter ) ;
501- dialog . set_filters ( filterList ) ;
512+ return emptyBox ;
513+ }
502514
503- dialog . open ( this . get_root ( ) , null , ( source , result ) => {
504- try {
505- const file = dialog . open_finish ( result ) ;
506- if ( file ) {
507- this . loadWallpaperWithoutExtraction ( file . get_path ( ) ) ;
508- }
509- } catch ( e ) {
510- if (
511- ! e . matches ( Gtk . DialogError , Gtk . DialogError . DISMISSED )
512- ) {
513- console . error ( 'Error selecting file:' , e . message ) ;
514- }
515+ _uploadWallpaper ( ) {
516+ uploadWallpaper (
517+ this . get_root ( ) ,
518+ ( destPath ) => {
519+ // Load the wallpaper from ~/Wallpapers
520+ this . loadWallpaperWithoutExtraction ( destPath ) ;
515521 }
516- } ) ;
522+ ) ;
517523 }
518524
519525 loadWallpaper ( path ) {
520526 // Load wallpaper without extraction - user must click extract button
521527 this . _currentWallpaper = path ;
522528
529+ // Hide empty state, show wallpaper controls
530+ this . _emptyStateBox . set_visible ( false ) ;
531+ this . _wallpaperGroup . set_visible ( true ) ;
532+
523533 // Force complete reload by using texture instead of file
524534 // This ensures GTK doesn't cache the old image
525535 try {
@@ -534,10 +544,6 @@ export const PaletteGenerator = GObject.registerClass(
534544 this . _wallpaperPreview . set_file ( file ) ;
535545 this . _wallpaperPreview . set_visible ( true ) ;
536546 }
537-
538- this . _imExtractButton . set_visible ( true ) ;
539- this . _pickFromWallpaperBtn . set_visible ( true ) ;
540- this . _editWallpaperBtn . set_visible ( true ) ;
541547 }
542548
543549 _onWallpaperBrowserSelected ( path ) {
@@ -552,6 +558,10 @@ export const PaletteGenerator = GObject.registerClass(
552558 // For manual selection - just show wallpaper and extract button, don't auto-extract
553559 this . _currentWallpaper = path ;
554560
561+ // Hide empty state, show wallpaper controls
562+ this . _emptyStateBox . set_visible ( false ) ;
563+ this . _wallpaperGroup . set_visible ( true ) ;
564+
555565 // Force complete reload by using texture instead of file
556566 try {
557567 const pixbuf = GdkPixbuf . Pixbuf . new_from_file ( path ) ;
@@ -565,10 +575,6 @@ export const PaletteGenerator = GObject.registerClass(
565575 this . _wallpaperPreview . set_file ( file ) ;
566576 this . _wallpaperPreview . set_visible ( true ) ;
567577 }
568-
569- this . _imExtractButton . set_visible ( true ) ;
570- this . _pickFromWallpaperBtn . set_visible ( true ) ;
571- this . _editWallpaperBtn . set_visible ( true ) ;
572578 }
573579
574580 _extractColorsIM ( imagePath ) {
@@ -776,11 +782,12 @@ export const PaletteGenerator = GObject.registerClass(
776782 this . _wallpaperPreview . set_visible ( false ) ;
777783 if ( this . _customWallpaperPreview ) {
778784 this . _customWallpaperPreview . set_file ( null ) ;
779- this . _customWallpaperPreview . set_visible ( false ) ;
780785 }
781- this . _imExtractButton . set_visible ( false ) ;
782- this . _pickFromWallpaperBtn . set_visible ( false ) ;
783- this . _editWallpaperBtn . set_visible ( false ) ;
786+
787+ // Show empty state, hide wallpaper controls
788+ this . _emptyStateBox . set_visible ( true ) ;
789+ this . _wallpaperGroup . set_visible ( false ) ;
790+
784791 this . _swatchGrid . setLockedColors ( new Array ( 16 ) . fill ( false ) ) ; // Reset all locks
785792 this . _showLoading ( false ) ;
786793
0 commit comments