From de81b9b43c92a6a8a1403c4547dc44dd17b9792e Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 9 Jun 2014 22:20:22 -0700 Subject: #171 Add a full UserFragment to view/edit settings --- src/github/daneren2005/dsub/domain/User.java | 126 ++++----------------- .../daneren2005/dsub/fragments/AdminFragment.java | 2 - .../daneren2005/dsub/fragments/UserFragment.java | 57 +++++++++- .../dsub/service/CachedMusicService.java | 4 + .../daneren2005/dsub/service/RESTMusicService.java | 17 ++- .../dsub/service/parser/UserParser.java | 28 +++-- src/github/daneren2005/dsub/view/SettingView.java | 68 +++++++++++ .../daneren2005/dsub/view/SettingsAdapter.java | 51 +++++++++ 8 files changed, 234 insertions(+), 119 deletions(-) create mode 100644 src/github/daneren2005/dsub/view/SettingView.java create mode 100644 src/github/daneren2005/dsub/view/SettingsAdapter.java (limited to 'src') diff --git a/src/github/daneren2005/dsub/domain/User.java b/src/github/daneren2005/dsub/domain/User.java index 63ead042..d970366c 100644 --- a/src/github/daneren2005/dsub/domain/User.java +++ b/src/github/daneren2005/dsub/domain/User.java @@ -16,24 +16,15 @@ package github.daneren2005.dsub.domain; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; public class User implements Serializable { private String username; private String password; private String email; - private Boolean scrobblingEnabled; - - private Boolean adminRole; - private Boolean settingsRole; - private Boolean downloadRole; - private Boolean uploadRole; - private Boolean playlistRole; - private Boolean coverArtRole; - private Boolean commentRole; - private Boolean podcastRole; - private Boolean streamRole; - private Boolean jukeboxRole; - private Boolean shareRole; + + private List settings = new ArrayList(); public User() { @@ -63,99 +54,30 @@ public class User implements Serializable { this.email = email; } - public Boolean getScrobblingEnabled() { - return scrobblingEnabled; - } - - public void setScrobblingEnabled(Boolean scrobblingEnabled) { - this.scrobblingEnabled = scrobblingEnabled; - } - - public Boolean getAdminRole() { - return adminRole; - } - - public void setAdminRole(Boolean adminRole) { - this.adminRole = adminRole; - } - - public Boolean getSettingsRole() { - return settingsRole; - } - - public void setSettingsRole(Boolean settingsRole) { - this.settingsRole = settingsRole; - } - - public Boolean getDownloadRole() { - return downloadRole; - } - - public void setDownloadRole(Boolean downloadRole) { - this.downloadRole = downloadRole; - } - - public Boolean getUploadRole() { - return uploadRole; - } - - public void setUploadRole(Boolean uploadRole) { - this.uploadRole = uploadRole; - } - - public Boolean getPlaylistRole() { - return playlistRole; + public List getSettings() { + return settings; } - - public void setPlaylistRole(Boolean playlistRole) { - this.playlistRole = playlistRole; - } - - public Boolean getCoverArtRole() { - return coverArtRole; + public void addSetting(String name, Boolean value) { + settings.add(new Setting(name, value)); } - public void setCoverArtRole(Boolean coverArtRole) { - this.coverArtRole = coverArtRole; - } - - public Boolean getCommentRole() { - return commentRole; - } + public static class Setting implements Serializable { + String name; + Boolean value; - public void setCommentRole(Boolean commentRole) { - this.commentRole = commentRole; - } - - public Boolean getPodcastRole() { - return podcastRole; - } - - public void setPodcastRole(Boolean podcastRole) { - this.podcastRole = podcastRole; - } - - public Boolean getStreamRole() { - return streamRole; - } - - public void setStreamRole(Boolean streamRole) { - this.streamRole = streamRole; - } - - public Boolean getJukeboxRole() { - return jukeboxRole; - } - - public void setJukeboxRole(Boolean jukeboxRole) { - this.jukeboxRole = jukeboxRole; - } - - public Boolean getShareRole() { - return shareRole; - } + public Setting(String name, Boolean value) { + this.name = name; + this.value = value; + } - public void setShareRole(Boolean shareRole) { - this.shareRole = shareRole; + public String getName() { + return name; + } + public Boolean getValue() { + return value; + } + public void setValue(Boolean value) { + this.value = value; + } } } diff --git a/src/github/daneren2005/dsub/fragments/AdminFragment.java b/src/github/daneren2005/dsub/fragments/AdminFragment.java index f6e8e153..faa7529a 100644 --- a/src/github/daneren2005/dsub/fragments/AdminFragment.java +++ b/src/github/daneren2005/dsub/fragments/AdminFragment.java @@ -61,8 +61,6 @@ public class AdminFragment extends SelectListFragment { User user = objects.get(info.position); switch(menuItem.getItemId()) { - case R.id.admin_update_permissions: - break; case R.id.admin_change_password: changePassword(user); break; diff --git a/src/github/daneren2005/dsub/fragments/UserFragment.java b/src/github/daneren2005/dsub/fragments/UserFragment.java index 3a85c6bb..1f4d4592 100644 --- a/src/github/daneren2005/dsub/fragments/UserFragment.java +++ b/src/github/daneren2005/dsub/fragments/UserFragment.java @@ -16,6 +16,7 @@ package github.daneren2005.dsub.fragments; import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -26,7 +27,14 @@ import android.widget.ListView; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.User; +import github.daneren2005.dsub.service.MusicService; +import github.daneren2005.dsub.service.MusicServiceFactory; +import github.daneren2005.dsub.service.OfflineException; +import github.daneren2005.dsub.service.ServerTooOldException; import github.daneren2005.dsub.util.Constants; +import github.daneren2005.dsub.util.SilentBackgroundTask; +import github.daneren2005.dsub.util.Util; +import github.daneren2005.dsub.view.SettingsAdapter; public class UserFragment extends SubsonicFragment{ private ListView listView; @@ -38,8 +46,15 @@ public class UserFragment extends SubsonicFragment{ this.inflater = inflater; rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false); + refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout); + refreshLayout.setEnabled(false); + Bundle args = getArguments(); user = (User) args.getSerializable(Constants.INTENT_EXTRA_NAME_ID); + + listView = (ListView)rootView.findViewById(R.id.fragment_list); + listView.setAdapter(new SettingsAdapter(context, user.getSettings(), true)); + setTitle(user.getUsername()); return rootView; @@ -51,11 +66,49 @@ public class UserFragment extends SubsonicFragment{ return; } - menuInflater.inflate(R.menu.empty, menu); + menuInflater.inflate(R.menu.user, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); + if(super.onOptionsItemSelected(item)) { + return true; + } + + switch (item.getItemId()) { + case R.id.menu_update_permissions: + updateSettings(); + return true; + } + + return false; + } + + private void updateSettings() { + new SilentBackgroundTask(context) { + @Override + protected Void doInBackground() throws Throwable { + MusicService musicService = MusicServiceFactory.getMusicService(context); + musicService.updateUser(user, context, null); + return null; + } + + @Override + protected void done(Void v) { + Util.toast(context, context.getResources().getString(R.string.admin_update_permissions_success, user.getUsername())); + } + + @Override + protected void error(Throwable error) { + String msg; + if (error instanceof OfflineException || error instanceof ServerTooOldException) { + msg = getErrorMessage(error); + } else { + msg = context.getResources().getString(R.string.admin_update_permissions_error, user.getUsername()); + } + + Util.toast(context, msg); + } + }.execute(); } } diff --git a/src/github/daneren2005/dsub/service/CachedMusicService.java b/src/github/daneren2005/dsub/service/CachedMusicService.java index 1f1715c4..86289511 100644 --- a/src/github/daneren2005/dsub/service/CachedMusicService.java +++ b/src/github/daneren2005/dsub/service/CachedMusicService.java @@ -547,6 +547,10 @@ public class CachedMusicService implements MusicService { @Override public void updateUser(User user, Context context, ProgressListener progressListener) throws Exception { musicService.updateUser(user, context, progressListener); + + // Delete cached users if anything updated + File file = new File(context.getCacheDir(), getCacheName(context, "users")); + file.delete(); } @Override diff --git a/src/github/daneren2005/dsub/service/RESTMusicService.java b/src/github/daneren2005/dsub/service/RESTMusicService.java index 20328d54..c2f64dad 100644 --- a/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -1230,7 +1230,22 @@ public class RESTMusicService implements MusicService { @Override public void updateUser(User user, Context context, ProgressListener progressListener) throws Exception { - Reader reader = getReader(context, progressListener, "createUser", null); + checkServerVersion(context, "1.10", "Updating user is not supported"); + + List names = new ArrayList(); + List values = new ArrayList(); + + names.add("username"); + values.add(user.getUsername()); + + for(User.Setting setting: user.getSettings()) { + if(setting.getName().indexOf("Role") != -1) { + names.add(setting.getName()); + values.add(setting.getValue()); + } + } + + Reader reader = getReader(context, progressListener, "updateUser", null, names, values); try { new ErrorParser(context).parse(reader); } finally { diff --git a/src/github/daneren2005/dsub/service/parser/UserParser.java b/src/github/daneren2005/dsub/service/parser/UserParser.java index a66e0b63..5b2f8fc1 100644 --- a/src/github/daneren2005/dsub/service/parser/UserParser.java +++ b/src/github/daneren2005/dsub/service/parser/UserParser.java @@ -46,18 +46,18 @@ public class UserParser extends AbstractParser { user.setUsername(get("username")); user.setEmail(get("email")); - user.setScrobblingEnabled(getBoolean("scrobblingEnabled")); - user.setAdminRole(getBoolean("adminRole")); - user.setSettingsRole(getBoolean("settingsRole")); - user.setDownloadRole(getBoolean("downloadRole")); - user.setUploadRole(getBoolean("uploadRole")); - user.setPlaylistRole(getBoolean("playlistRole")); - user.setCoverArtRole(getBoolean("coverArtRole")); - user.setCommentRole(getBoolean("commentRole")); - user.setPodcastRole(getBoolean("podcastRole")); - user.setStreamRole(getBoolean("streamRole")); - user.setJukeboxRole(getBoolean("jukeboxRole")); - user.setShareRole(getBoolean("shareRole")); + parseSetting(user, "scrobblingEnabled"); + parseSetting(user, "adminRole"); + parseSetting(user, "settingsRole"); + parseSetting(user, "downloadRole"); + parseSetting(user, "uploadRole"); + // Depreciated: parseSetting(user, "playlistRole"); + parseSetting(user, "coverArtRole"); + parseSetting(user, "commentRole"); + parseSetting(user, "podcastRole"); + parseSetting(user, "streamRole"); + parseSetting(user, "jukeboxRole"); + parseSetting(user, "shareRole"); result.add(user); } else if ("error".equals(name)) { @@ -70,4 +70,8 @@ public class UserParser extends AbstractParser { return result; } + + private void parseSetting(User user, String name) { + user.addSetting(name, getBoolean(name)); + } } \ No newline at end of file diff --git a/src/github/daneren2005/dsub/view/SettingView.java b/src/github/daneren2005/dsub/view/SettingView.java new file mode 100644 index 00000000..f2669551 --- /dev/null +++ b/src/github/daneren2005/dsub/view/SettingView.java @@ -0,0 +1,68 @@ +/* + This file is part of Subsonic. + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see . + Copyright 2014 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.view; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckedTextView; + +import static github.daneren2005.dsub.domain.User.Setting; + +public class SettingView extends UpdateView { + Setting setting; + + CheckedTextView view; + + public SettingView(Context context) { + super(context); + this.context = context; + LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_multiple_choice, this, true); + + view = (CheckedTextView) findViewById(android.R.id.text1); + } + + protected void setObjectImpl(Object obj, Object editable) { + this.setting = (Setting) obj; + + String display = setting.getName(); + // Can't edit non-role parts + if(display.indexOf("Role") == -1) { + editable = false; + } + display = display.replace("Role", ""); + display = Character.toUpperCase(display.charAt(0)) + display.substring(1); + + view.setText(display); + if(setting.getValue()) { + view.setChecked(setting.getValue()); + } else { + view.setChecked(false); + } + + if((Boolean) editable) { + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + view.toggle(); + setting.setValue(view.isChecked()); + } + }); + } else { + view.setOnClickListener(null); + } + } +} diff --git a/src/github/daneren2005/dsub/view/SettingsAdapter.java b/src/github/daneren2005/dsub/view/SettingsAdapter.java new file mode 100644 index 00000000..88019c00 --- /dev/null +++ b/src/github/daneren2005/dsub/view/SettingsAdapter.java @@ -0,0 +1,51 @@ +/* + This file is part of Subsonic. + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see . + Copyright 2014 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.view; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; + +import java.util.List; + +import github.daneren2005.dsub.R; + +import static github.daneren2005.dsub.domain.User.Setting; + +public class SettingsAdapter extends ArrayAdapter { + private final Context context; + private final boolean editable; + + public SettingsAdapter(Context context, List settings, boolean editable) { + super(context, R.layout.basic_list_item, settings); + this.context = context; + this.editable = editable; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + Setting entry = getItem(position); + SettingView view; + if (convertView != null && convertView instanceof SettingView) { + view = (SettingView) convertView; + } else { + view = new SettingView(context); + } + view.setObject(entry, editable); + return view; + } +} -- cgit v1.2.3