hunk.code_window: 					allowHighlight && ['bg-accent', !isDark && 'text-white']
   			)}
   			style={props.style}
   			lines={props.lines}
   			idleClassName={props.idleClassName}
   		/>
   	);
   };
hunk.labels: keep keep keep keep add keep keep keep
hunk.after_edit: 			toggleBy={props.toggleBy}
  
hunk.file_path: interface/app/$libraryId/Explorer/View/RenamableItemText.tsx
hunk.type: add
file: use std::path::{Path, PathBuf};
  
  use gtk::{
  	gio::{
  		content_type_guess,
  		prelude::AppInfoExt,
  		prelude::{AppLaunchContextExt, FileExt},
  		AppInfo, AppLaunchContext, DesktopAppInfo, File as GioFile, ResourceError,
  	},
  	glib::error::Error as GlibError,
  	prelude::IsA,
  };
  use tokio::fs::File;
  use tokio::io::AsyncReadExt;
  
  use crate::env::remove_prefix_from_pathlist;
  
  fn remove_prefix_from_env_in_ctx(
  	ctx: &impl IsA<AppLaunchContext>,
  	env_name: &str,
  	prefix: &impl AsRef<Path>,
  ) {
  	if let Some(value) = remove_prefix_from_pathlist(env_name, prefix) {
  		ctx.setenv(env_name, value);
  	} else {
  		ctx.unsetenv(env_name);
  	}
  }
  
  thread_local! {
  	static LAUNCH_CTX: AppLaunchContext = {
  		// TODO: Display supports requires GDK, which can only run on the main thread
  		// let ctx = Display::default()
  		// 		.and_then(|display| display.app_launch_context())
  		// 		.map(|display| display.to_value().get::<AppLaunchContext>().expect(
  		// 			"This is an Glib type conversion, it should never fail because GDKAppLaunchContext is a subclass of AppLaunchContext"
  		// 		)).unwrap_or_default();
  
  		let ctx = AppLaunchContext::default();
  
  		if let Some(appdir) = std::env::var_os("APPDIR").map(PathBuf::from) {
  			// Remove AppImage paths from environment variables to avoid external applications attempting to use the AppImage's libraries
  			// https://github.com/AppImage/AppImageKit/blob/701b711f42250584b65a88f6427006b1d160164d/src/AppRun.c#L168-L194
  			ctx.unsetenv("PYTHONHOME");
  			ctx.unsetenv("GTK_DATA_PREFIX");
  			ctx.unsetenv("GTK_THEME");
  			ctx.unsetenv("GDK_BACKEND");
  			ctx.unsetenv("GTK_EXE_PREFIX");
  			ctx.unsetenv("GTK_IM_MODULE_FILE");
  			ctx.unsetenv("GDK_PIXBUF_MODULE_FILE");
  
  			remove_prefix_from_env_in_ctx(&ctx, "PATH", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "LD_LIBRARY_PATH", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "PYTHONPATH", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "XDG_DATA_DIRS", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "PERLLIB", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "GSETTINGS_SCHEMA_DIR", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "QT_PLUGIN_PATH", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "GST_PLUGIN_SYSTEM_PATH", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "GST_PLUGIN_SYSTEM_PATH_1_0", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "GTK_PATH", &appdir);
  			remove_prefix_from_env_in_ctx(&ctx, "GIO_EXTRA_MODULES", &appdir);
  		}
  
  		ctx
  	}
  }
  
  pub struct App {
  	pub id: String,
  	pub name: String,
  	// pub icon: Option<Vec<u8>>,
  }
  
  async fn recommended_for_type(file_path: impl AsRef<Path>) -> Vec<AppInfo> {
  	let data = if let Ok(mut file) = File::open(&file_path).await {
  		let mut data = [0; 1024];
  		if file.read_exact(&mut data).await.is_ok() {
  			Some(data)
  		} else {
  			None
  		}
  	} else {
  		None
  	};
  
  	let file_path = Some(file_path);
  	let (content_type, uncertain) = if let Some(data) = data {
  		content_type_guess(file_path, &data)
  	} else {
  		content_type_guess(file_path, &[])
  	};
  
  	if uncertain {
  		vec![]
  	} else {
  		AppInfo::recommended_for_type(content_type.as_str())
  	}
  }
  
  pub async fn list_apps_associated_with_ext(file_path: impl AsRef<Path>) -> Vec<App> {
  	recommended_for_type(file_path)
  		.await
  		.iter()
  		.flat_map(|app_info| {
  			app_info.id().map(|id| App {
  				id: id.to_string(),
  				name: app_info.name().to_string(),
  				// TODO: Icon supports requires GTK, which can only run on the main thread
  				// icon: app_info
  				// 	.icon()
  				// 	.and_then(|icon| {
  				// 		IconTheme::default().and_then(|icon_theme| {
  				// 			icon_theme.lookup_by_gicon(&icon, 128, IconLookupFlags::empty())
  				// 		})
  				// 	})
  				// 	.and_then(|icon_info| icon_info.load_icon().ok())
  				// 	.and_then(|pixbuf| pixbuf.save_to_bufferv("png", &[]).ok()),
  			})
  		})
  		.collect()
  }
  
  pub fn open_files_path_with(file_paths: &[impl AsRef<Path>], id: &str) -> Result<(), GlibError> {
  	let Some(app) = DesktopAppInfo::new(id) else {
  		return Err(GlibError::new(ResourceError::NotFound, "App not found"));
  	};
  
  	LAUNCH_CTX.with(|ctx| {
  		app.launch(
  			&file_paths.iter().map(GioFile::for_path).collect::<Vec<_>>(),
  			Some(ctx),
  		)
  	})
  }
  
  pub fn open_file_path(file_path: impl AsRef<Path>) -> Result<(), GlibError> {
  	let file_uri = GioFile::for_path(file_path).uri().to_string();
  	LAUNCH_CTX.with(|ctx| AppInfo::launch_default_for_uri(&file_uri.to_string(), Some(ctx)))
  }
  