tytd-mobile/TYTD.Mobile/Servers.cs

441 lines
15 KiB
C#
Raw Permalink Normal View History

2022-10-04 10:44:09 +00:00
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using AndroidX.AppCompat.App;
using AndroidX.AppCompat.Widget;
using AndroidX.Core.View;
using AndroidX.DrawerLayout.Widget;
using Google.Android.Material.FloatingActionButton;
using Google.Android.Material.Navigation;
using Google.Android.Material.Snackbar;
using Tesses.YouTubeDownloader.Droid;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
namespace TYTD.Mobile
{
public interface IServerItem
{
bool IsEditable {get;}
string Name {get;set;}
string InnerValue {get;set;}
bool Update();
void Delete();
}
public sealed class LocalItem : IServerItem
{
string name;
string value;
public LocalItem(string name,string value)
{
this.name = name;
this.value = value;
}
public bool IsEditable => false;
public string Name { get => name; set => throw new NotImplementedException(); }
public string InnerValue { get => value; set => throw new NotImplementedException(); }
public void Delete()
{
throw new NotImplementedException();
}
public bool Update()
{
throw new NotImplementedException();
}
}
public sealed class ServerItem : IServerItem
{
string oldname;
Dictionary<string,string> dict;
public ServerItem(Dictionary<string,string> dict,string name,string url)
{
oldname=name;
Name = name;
InnerValue=url;
this.dict=dict;
}
public bool IsEditable => true;
public string Name {get;set;}
public string InnerValue {
get;set;
}
public void Delete()
{
dict.Remove(oldname);
TYTDCommon.SaveServers(dict);
}
public bool Update()
{
if(oldname != Name)
{
dict.Remove(oldname);
dict.Add(Name,InnerValue);
TYTDCommon.SaveServers(dict);
return true;
}
dict[Name]=InnerValue;
TYTDCommon.SaveServers(dict);
return false;
}
}
public static class ServerItemHandler
{
public static string AddUnique<T>(this Dictionary<string,T> items,string key,T value)
{
string keyOut=key;
int i = 2;
while(items.ContainsKey(keyOut))
{
keyOut = $"{key} ({i++})";
}
items.Add(keyOut,value);
return keyOut;
}
private static IEnumerable<string> getNames(this IEnumerable<IServerItem> items)
{
foreach(var item in items)
{
yield return item.Name;
}
}
public static string[] GetNames(this IEnumerable<IServerItem> items)
{
return items.getNames().ToArray();
}
}
[Activity(Label = "@string/servers_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = false)]
public class ServersActivity : AppCompatActivity
{
public void UpdateItem(IServerItem item)
{
var builder=new AndroidX.AppCompat.App.AlertDialog.Builder(this);
builder.SetView(Resource.Layout.edit_server);
EditText? name =null;
EditText? url=null;
Button? sftp=null;
AndroidX.AppCompat.App.AlertDialog? alert=null;
builder.SetNegativeButton(Resource.String.cancel_text,(sender,e)=>{
if(alert != null) alert.Dismiss();
});
builder.SetTitle(Resource.String.edit_server_text);
builder.SetPositiveButton(Resource.String.ok_text,(sender,e)=>{
if(svrs != null&&name!= null && url !=null && !string.IsNullOrWhiteSpace(name.Text) && !string.IsNullOrWhiteSpace(url.Text)){
item.Name = name.Text;
item.InnerValue = url.Text;
if(item.Update())
UpdateLV();
}
if(alert != null) alert.Dismiss();
});
alert= builder.Show();
if(alert != null)
{
//this.GetExternalFilesDirs(null)
name=alert.FindViewById<EditText>(Resource.Id.server_name_field);
if(name!= null)
name.Text = item.Name;
url = alert.FindViewById<EditText>(Resource.Id.server_uri_field);
if(url != null)
url.Text = item.InnerValue;
sftp = alert.FindViewById<Button>(Resource.Id.server_ssh_button);
if(sftp != null)
{
sftp.Click += (sender,e)=>{
if(url != null)
{
SftpEditor(url);
}
};
}
}
}
Dictionary<string,string> svrs=new();
List<IServerItem> items=new List<IServerItem>();
ListView? listView=null;
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_servers);
Toolbar? toolbar = FindViewById<Toolbar>(Resource.Id.toolbar_servers);
if(toolbar != null)
{
SetSupportActionBar(toolbar);
SupportActionBar?.SetDisplayHomeAsUpEnabled(true);
SupportActionBar?.SetDisplayShowHomeEnabled(true);
}
FloatingActionButton? fab = FindViewById<FloatingActionButton>(Resource.Id.add_server);
if(fab != null)
fab.Click += FabOnClick;
listView = FindViewById<ListView>(Resource.Id.server_list);
if(listView!=null)
{
listView.ItemClick += (sender,e)=>{
IServerItem item = items[e.Position];
Android.Widget.PopupMenu menu=new Android.Widget.PopupMenu(this,e.View);
menu.MenuItemClick += (sender2,e2)=>{
if(e2.Item != null)
switch(e2.Item.ItemId)
{
case Resource.Id.action_storage_set:
case Resource.Id.action_storage_setne:
TYTDCommon.AppStorageLocation = item.InnerValue;
//set storage
break;
case Resource.Id.action_download_set:
case Resource.Id.action_download_setne:
TYTDCommon.AppDownloadLocation = item.InnerValue;
//set download to
break;
case Resource.Id.action_edit_server:
if(item.IsEditable){
UpdateItem(item);
}
break;
case Resource.Id.action_delete_server:
if(item.IsEditable){
item.Delete();
UpdateLV();
}
break;
}
};
menu.Inflate(item.IsEditable ? Resource.Menu.menu_server_editable : Resource.Menu.menu_server_not_editable);
menu.Show();
};
UpdateLV();
}
}
public void UpdateLV()
{
if(listView != null)
{
items.Clear();
foreach(var storage in TYTDCommon.GetStorageDevices())
{
items.Add(new LocalItem(storage.Label,storage.Path));
}
svrs=TYTDCommon.GetServers();
foreach(var svr in svrs)
{
items.Add(new ServerItem(svrs,svr.Key,svr.Value));
}
listView.Adapter = new ArrayAdapter<string>(this,Android.Resource.Layout.SimpleListItem1,items.GetNames());
}
}
public override bool OnSupportNavigateUp()
{
OnBackPressed();
return true;
}
public override bool OnCreateOptionsMenu(IMenu? menu)
{
MenuInflater.Inflate(Resource.Menu.menu_servers, menu);
return true;
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
int id = item.ItemId;
return base.OnOptionsItemSelected(item);
}
private void FabOnClick(object? sender, EventArgs eventArgs)
{
var builder=new AndroidX.AppCompat.App.AlertDialog.Builder(this);
builder.SetView(Resource.Layout.edit_server);
EditText? name =null;
EditText? url=null;
Button? sftp=null;
AndroidX.AppCompat.App.AlertDialog? alert=null;
builder.SetTitle(Resource.String.add_server_text);
builder.SetNegativeButton(Resource.String.cancel_text,(sender,e)=>{
if(alert != null) alert.Dismiss();
});
builder.SetPositiveButton(Resource.String.ok_text,(sender,e)=>{
if(svrs != null&&name!= null && url !=null && !string.IsNullOrWhiteSpace(name.Text) && !string.IsNullOrWhiteSpace(url.Text)){
svrs.AddUnique(name.Text,url.Text);
TYTDCommon.SaveServers(svrs);
UpdateLV();
}
if(alert != null) alert.Dismiss();
});
alert= builder.Show();
if(alert != null)
{
//this.GetExternalFilesDirs(null)
name=alert.FindViewById<EditText>(Resource.Id.server_name_field);
url = alert.FindViewById<EditText>(Resource.Id.server_uri_field);
sftp = alert.FindViewById<Button>(Resource.Id.server_ssh_button);
if(sftp != null)
{
sftp.Click += (sender,e)=>{
if(url != null)
{
SftpEditor(url);
}
};
}
}
}
private void SftpEditor(EditText uriText)
{
Uri? uri;
string ipOrFqdn="";
string port="";
string username="";
string password="";
string path="";
if(Uri.TryCreate(uriText.Text,UriKind.Absolute,out uri) && uri.Scheme == "sftp")
{
ipOrFqdn = uri.Host;
port = uri.Port.ToString();
string userInfo=uri.UserInfo;
if(!string.IsNullOrWhiteSpace(userInfo))
{
string[] userInfoSplit = userInfo.Split(':',2,StringSplitOptions.RemoveEmptyEntries);
if(userInfoSplit.Length == 2)
{
//username:password
username = userInfoSplit[0];
password = userInfoSplit[1];
}else if(userInfoSplit.Length == 1)
{
//username only
username = userInfoSplit[0];
}
}
path=uri.PathAndQuery;
}
EditText? fqdnTb=null;
EditText? portTb=null;
EditText? usernameTb=null;
EditText? passwordTb=null;
EditText? pathTb=null;
AndroidX.AppCompat.App.AlertDialog? alert=null;
var builder=new AndroidX.AppCompat.App.AlertDialog.Builder(this);
builder.SetTitle(Resource.String.edit_ssh_text);
builder.SetView(Resource.Layout.edit_ssh_server);
builder.SetPositiveButton(Resource.String.ok_text,(sender,e)=>{
if(fqdnTb != null)
{
ipOrFqdn=fqdnTb.Text.GetValOrDefault();
}
if(portTb != null)
{
ushort portN;
if(ushort.TryParse(portTb.Text,out portN))
{
port=portN.ToString();
}else{
port="22";
}
}
if(usernameTb != null)
{
username=usernameTb.Text.GetValOrDefault();
}
if(passwordTb != null)
{
password = passwordTb.Text.GetValOrDefault();
}
if(pathTb != null)
{
path = pathTb.Text.GetValOrDefault();
}
string userInfoStr="";
bool hasUserName = !string.IsNullOrWhiteSpace(username);
bool hasPassword = !string.IsNullOrWhiteSpace(password);
if(hasUserName || hasPassword)
{
if(hasUserName && !hasPassword)
{
userInfoStr = $"{username}@";
}
else if(hasPassword && !hasUserName)
{
userInfoStr = $"root:{password}@";
}else{
userInfoStr = $"{username}:{password}@";
}
}
if(string.IsNullOrWhiteSpace(path)) path="/";
string url = $"sftp://{userInfoStr}{ipOrFqdn}:{port}{path}";
uriText.Text=url;
if(alert!= null) alert.Dismiss();
});
builder.SetNegativeButton(Resource.String.cancel_text,(sender,e)=>{
if(alert != null) alert.Dismiss();
});
alert=builder.Show();
if(alert != null){
fqdnTb=alert.FindViewById<EditText>(Resource.Id.ssh_uri);
if(fqdnTb != null)
fqdnTb.Text = ipOrFqdn;
portTb=alert.FindViewById<EditText>(Resource.Id.ssh_port);
if(portTb != null)
portTb.Text = port;
usernameTb=alert.FindViewById<EditText>(Resource.Id.ssh_username);
if(usernameTb!= null)
usernameTb.Text=username;
passwordTb = alert.FindViewById<EditText>(Resource.Id.ssh_password);
if(passwordTb !=null)
passwordTb.Text=password;
pathTb = alert.FindViewById<EditText>(Resource.Id.ssh_path);
if(pathTb != null)
pathTb.Text = path;
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}