After Width: | Height: | Size: 344 B |
@ -0,0 +1,29 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program 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. |
||||
* |
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.core.database; |
||||
|
||||
|
||||
public class DatabaseSiteManager { |
||||
private DatabaseManager databaseManager; |
||||
private DatabaseHelper databaseHelper; |
||||
|
||||
public DatabaseSiteManager(DatabaseManager databaseManager, DatabaseHelper databaseHelper) { |
||||
this.databaseManager = databaseManager; |
||||
this.databaseHelper = databaseHelper; |
||||
} |
||||
} |
@ -1,131 +0,0 @@ |
||||
package org.floens.chan.core.di; |
||||
|
||||
import com.android.volley.RequestQueue; |
||||
import com.android.volley.toolbox.ImageLoader; |
||||
|
||||
import org.floens.chan.Chan; |
||||
import org.floens.chan.chan.ChanLoader; |
||||
import org.floens.chan.chan.ChanParser; |
||||
import org.floens.chan.core.cache.FileCache; |
||||
import org.floens.chan.core.database.DatabaseManager; |
||||
import org.floens.chan.core.manager.BoardManager; |
||||
import org.floens.chan.core.manager.FilterEngine; |
||||
import org.floens.chan.core.manager.ReplyManager; |
||||
import org.floens.chan.core.manager.WatchManager; |
||||
import org.floens.chan.core.presenter.ImageViewerPresenter; |
||||
import org.floens.chan.core.presenter.ReplyPresenter; |
||||
import org.floens.chan.core.presenter.ThreadPresenter; |
||||
import org.floens.chan.core.receiver.WatchUpdateReceiver; |
||||
import org.floens.chan.core.saver.ImageSaveTask; |
||||
import org.floens.chan.core.site.http.HttpCallManager; |
||||
import org.floens.chan.core.site.sites.chan4.Chan4; |
||||
import org.floens.chan.core.site.sites.chan4.Chan4ReaderRequest; |
||||
import org.floens.chan.core.update.UpdateManager; |
||||
import org.floens.chan.ui.activity.StartActivity; |
||||
import org.floens.chan.ui.adapter.DrawerAdapter; |
||||
import org.floens.chan.ui.adapter.PostsFilter; |
||||
import org.floens.chan.ui.controller.BoardEditController; |
||||
import org.floens.chan.ui.controller.BrowseController; |
||||
import org.floens.chan.ui.controller.DeveloperSettingsController; |
||||
import org.floens.chan.ui.controller.DrawerController; |
||||
import org.floens.chan.ui.controller.FiltersController; |
||||
import org.floens.chan.ui.controller.HistoryController; |
||||
import org.floens.chan.ui.controller.ImageViewerController; |
||||
import org.floens.chan.ui.controller.MainSettingsController; |
||||
import org.floens.chan.ui.controller.PassSettingsController; |
||||
import org.floens.chan.ui.controller.ViewThreadController; |
||||
import org.floens.chan.ui.helper.ImagePickDelegate; |
||||
import org.floens.chan.ui.layout.FilterLayout; |
||||
import org.floens.chan.ui.layout.ThreadLayout; |
||||
import org.floens.chan.ui.service.WatchNotifier; |
||||
import org.floens.chan.ui.view.MultiImageView; |
||||
|
||||
import javax.inject.Singleton; |
||||
|
||||
import dagger.Component; |
||||
|
||||
@Component(modules = { |
||||
AppModule.class, |
||||
NetModule.class |
||||
}) |
||||
@Singleton |
||||
/** |
||||
* Note: please avoid adding inject() statements for Sites. |
||||
*/ |
||||
public interface ChanGraph { |
||||
ChanParser getChanParser(); |
||||
|
||||
BoardManager getBoardManager(); |
||||
|
||||
DatabaseManager getDatabaseManager(); |
||||
|
||||
ReplyManager getReplyManager(); |
||||
|
||||
RequestQueue getRequestQueue(); |
||||
|
||||
ImageLoader getImageLoader(); |
||||
|
||||
FileCache getFileCache(); |
||||
|
||||
HttpCallManager getHttpCallManager(); |
||||
|
||||
void inject(Chan chan); |
||||
|
||||
void inject(MainSettingsController mainSettingsController); |
||||
|
||||
void inject(ReplyPresenter replyPresenter); |
||||
|
||||
void inject(Chan4ReaderRequest chanReaderRequest); |
||||
|
||||
void inject(ThreadLayout threadLayout); |
||||
|
||||
void inject(DeveloperSettingsController developerSettingsController); |
||||
|
||||
void inject(StartActivity startActivity); |
||||
|
||||
void inject(ThreadPresenter threadPresenter); |
||||
|
||||
void inject(BoardEditController boardEditController); |
||||
|
||||
void inject(FilterEngine filterEngine); |
||||
|
||||
void inject(BrowseController browseController); |
||||
|
||||
void inject(FilterLayout filterLayout); |
||||
|
||||
void inject(HistoryController historyController); |
||||
|
||||
void inject(DrawerController drawerController); |
||||
|
||||
void inject(DrawerAdapter drawerAdapter); |
||||
|
||||
void inject(WatchNotifier watchNotifier); |
||||
|
||||
void inject(WatchUpdateReceiver watchUpdateReceiver); |
||||
|
||||
void inject(ImagePickDelegate imagePickDelegate); |
||||
|
||||
void inject(PassSettingsController passSettingsController); |
||||
|
||||
void inject(FiltersController filtersController); |
||||
|
||||
void inject(PostsFilter postsFilter); |
||||
|
||||
void inject(ChanLoader chanLoader); |
||||
|
||||
void inject(ImageViewerController imageViewerController); |
||||
|
||||
void inject(ImageViewerPresenter imageViewerPresenter); |
||||
|
||||
void inject(MultiImageView multiImageView); |
||||
|
||||
void inject(ImageSaveTask imageSaveTask); |
||||
|
||||
void inject(ViewThreadController viewThreadController); |
||||
|
||||
void inject(WatchManager.PinWatcher pinWatcher); |
||||
|
||||
void inject(UpdateManager updateManager); |
||||
|
||||
void inject(Chan4 chan4); |
||||
} |
@ -0,0 +1,29 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program 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. |
||||
* |
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.core.manager; |
||||
|
||||
|
||||
import javax.inject.Inject; |
||||
import javax.inject.Singleton; |
||||
|
||||
@Singleton |
||||
public class SiteManager { |
||||
@Inject |
||||
public SiteManager() { |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program 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. |
||||
* |
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.core.model; |
||||
|
||||
import com.j256.ormlite.field.DatabaseField; |
||||
import com.j256.ormlite.table.DatabaseTable; |
||||
|
||||
/** |
||||
* Only for storing what sites we know of, for hardcoded sites the sites we have enabled, |
||||
* and for dynamic sites all settings for it. |
||||
*/ |
||||
@DatabaseTable |
||||
public class SiteModel { |
||||
@DatabaseField(id = true, unique = true) |
||||
public int id; |
||||
|
||||
@DatabaseField |
||||
public String name; |
||||
|
||||
@DatabaseField |
||||
public String options; |
||||
} |
@ -0,0 +1,120 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program 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. |
||||
* |
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.core.presenter; |
||||
|
||||
|
||||
import android.graphics.Bitmap; |
||||
import android.graphics.BitmapFactory; |
||||
import android.graphics.drawable.BitmapDrawable; |
||||
import android.graphics.drawable.Drawable; |
||||
|
||||
import org.floens.chan.utils.AndroidUtils; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import static org.floens.chan.utils.AndroidUtils.getAppContext; |
||||
import static org.floens.chan.utils.AndroidUtils.getRes; |
||||
|
||||
public class SetupPresenter { |
||||
private Callback callback; |
||||
|
||||
private List<AddedSite> sites = new ArrayList<>(); |
||||
|
||||
public void create(Callback callback) { |
||||
this.callback = callback; |
||||
|
||||
this.callback.setAddedSites(sites); |
||||
|
||||
this.callback.setNextAllowed(!sites.isEmpty(), false); |
||||
} |
||||
|
||||
public boolean mayExit() { |
||||
return false; |
||||
} |
||||
|
||||
public void onUrlSubmitClicked(String url) { |
||||
callback.goToUrlSubmittedState(); |
||||
|
||||
AndroidUtils.runOnUiThread(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
siteAdded(getTestSite()); |
||||
} |
||||
}, 500); |
||||
// callback.showUrlHint("foo bar baz");
|
||||
} |
||||
|
||||
public void onNextClicked() { |
||||
if (!sites.isEmpty()) { |
||||
callback.moveToSavedBoards(); |
||||
} |
||||
} |
||||
|
||||
private void siteAdded(AddedSite site) { |
||||
sites.add(site); |
||||
callback.setAddedSites(sites); |
||||
callback.runSiteAddedAnimation(site); |
||||
|
||||
callback.setNextAllowed(!sites.isEmpty(), true); |
||||
} |
||||
|
||||
private int counter; |
||||
|
||||
private AddedSite getTestSite() { |
||||
AddedSite site = new AddedSite(); |
||||
site.id = counter++; |
||||
site.title = "4chan.org"; |
||||
|
||||
Bitmap bitmap; |
||||
try { |
||||
BitmapFactory.Options opts = new BitmapFactory.Options(); |
||||
opts.inScaled = false; |
||||
bitmap = BitmapFactory.decodeStream(getAppContext().getAssets().open("icons/4chan.png"), null, opts); |
||||
} catch (IOException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
|
||||
BitmapDrawable drawable = new BitmapDrawable(getRes(), bitmap); |
||||
drawable = (BitmapDrawable) drawable.mutate(); |
||||
drawable.getPaint().setFilterBitmap(false); |
||||
site.drawable = drawable; |
||||
return site; |
||||
} |
||||
|
||||
public interface Callback { |
||||
void goToUrlSubmittedState(); |
||||
|
||||
void runSiteAddedAnimation(AddedSite site); |
||||
|
||||
void setAddedSites(List<AddedSite> sites); |
||||
|
||||
void setNextAllowed(boolean nextAllowed, boolean animate); |
||||
|
||||
void showUrlHint(String text); |
||||
|
||||
void moveToSavedBoards(); |
||||
} |
||||
|
||||
public static class AddedSite { |
||||
public int id; |
||||
public String title; |
||||
public Drawable drawable; |
||||
} |
||||
} |
@ -0,0 +1,72 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program 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. |
||||
* |
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.core.site; |
||||
|
||||
|
||||
import android.graphics.Bitmap; |
||||
import android.graphics.BitmapFactory; |
||||
import android.graphics.drawable.BitmapDrawable; |
||||
import android.graphics.drawable.Drawable; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import okhttp3.HttpUrl; |
||||
|
||||
import static org.floens.chan.utils.AndroidUtils.getAppContext; |
||||
import static org.floens.chan.utils.AndroidUtils.getRes; |
||||
|
||||
public class SiteIcon { |
||||
private String assetPath; |
||||
private HttpUrl url; |
||||
|
||||
public static SiteIcon fromAssets(String path) { |
||||
SiteIcon siteIcon = new SiteIcon(); |
||||
siteIcon.assetPath = path; |
||||
return siteIcon; |
||||
} |
||||
|
||||
public static SiteIcon fromUrl(HttpUrl url) { |
||||
SiteIcon siteIcon = new SiteIcon(); |
||||
siteIcon.url = url; |
||||
return siteIcon; |
||||
} |
||||
|
||||
public void get(SiteIconResult result) { |
||||
if (assetPath != null) { |
||||
Bitmap bitmap; |
||||
try { |
||||
BitmapFactory.Options opts = new BitmapFactory.Options(); |
||||
opts.inScaled = false; |
||||
bitmap = BitmapFactory.decodeStream(getAppContext().getAssets().open(assetPath), null, opts); |
||||
} catch (IOException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
|
||||
BitmapDrawable drawable = new BitmapDrawable(getRes(), bitmap); |
||||
drawable = (BitmapDrawable) drawable.mutate(); |
||||
drawable.getPaint().setFilterBitmap(false); |
||||
result.onSiteIcon(this, drawable); |
||||
} else if (url != null) { |
||||
// TODO
|
||||
} |
||||
} |
||||
|
||||
public interface SiteIconResult { |
||||
void onSiteIcon(SiteIcon siteIcon, Drawable icon); |
||||
} |
||||
} |
@ -0,0 +1,178 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program 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. |
||||
* |
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.ui.controller; |
||||
|
||||
|
||||
import android.content.Context; |
||||
import android.graphics.Bitmap; |
||||
import android.graphics.BitmapFactory; |
||||
import android.graphics.drawable.BitmapDrawable; |
||||
import android.support.v7.widget.LinearLayoutManager; |
||||
import android.support.v7.widget.RecyclerView; |
||||
import android.view.LayoutInflater; |
||||
import android.view.View; |
||||
import android.view.ViewGroup; |
||||
import android.widget.ArrayAdapter; |
||||
import android.widget.AutoCompleteTextView; |
||||
import android.widget.ImageView; |
||||
import android.widget.TextView; |
||||
|
||||
import org.floens.chan.R; |
||||
import org.floens.chan.controller.Controller; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import static org.floens.chan.utils.AndroidUtils.getAppContext; |
||||
import static org.floens.chan.utils.AndroidUtils.getRes; |
||||
|
||||
public class BoardSetupController extends Controller implements View.OnClickListener { |
||||
private AutoCompleteTextView code; |
||||
private RecyclerView savedBoardsRecycler; |
||||
|
||||
private SavedBoardsAdapter adapter; |
||||
|
||||
public BoardSetupController(Context context) { |
||||
super(context); |
||||
} |
||||
|
||||
@Override |
||||
public void onCreate() { |
||||
super.onCreate(); |
||||
|
||||
view = inflateRes(R.layout.controller_board_setup); |
||||
navigationItem.setTitle(R.string.saved_boards_title); |
||||
|
||||
code = (AutoCompleteTextView) view.findViewById(R.id.code); |
||||
savedBoardsRecycler = (RecyclerView) view.findViewById(R.id.boards_recycler); |
||||
savedBoardsRecycler.setLayoutManager(new LinearLayoutManager(context)); |
||||
|
||||
adapter = new SavedBoardsAdapter(); |
||||
savedBoardsRecycler.setAdapter(adapter); |
||||
|
||||
List<SavedBoard> savedBoards = new ArrayList<>(); |
||||
for (int board = 0; board < 5; board++) { |
||||
savedBoards.add(new SavedBoard("foo - " + board, board)); |
||||
} |
||||
|
||||
adapter.setSavedBoards(savedBoards); |
||||
|
||||
List<String> foo = new ArrayList<String>() {{ |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("foo"); |
||||
add("bar"); |
||||
add("baz"); |
||||
}}; |
||||
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(context, android.R.layout.simple_dropdown_item_1line, foo); |
||||
code.setAdapter(adapter); |
||||
code.setThreshold(1); |
||||
} |
||||
|
||||
@Override |
||||
public void onClick(View v) { |
||||
} |
||||
|
||||
private class SavedBoard { |
||||
private String title; |
||||
private int id; |
||||
|
||||
public SavedBoard(String title, int id) { |
||||
this.title = title; |
||||
this.id = id; |
||||
} |
||||
} |
||||
|
||||
private class SavedBoardsAdapter extends RecyclerView.Adapter<SavedBoardCell> { |
||||
private List<SavedBoard> savedBoards = new ArrayList<>(); |
||||
|
||||
public SavedBoardsAdapter() { |
||||
setHasStableIds(true); |
||||
} |
||||
|
||||
private void setSavedBoards(List<SavedBoard> savedBoards) { |
||||
this.savedBoards.clear(); |
||||
this.savedBoards.addAll(savedBoards); |
||||
notifyDataSetChanged(); |
||||
} |
||||
|
||||
@Override |
||||
public long getItemId(int position) { |
||||
return savedBoards.get(position).id; |
||||
} |
||||
|
||||
@Override |
||||
public SavedBoardCell onCreateViewHolder(ViewGroup parent, int viewType) { |
||||
return new SavedBoardCell(LayoutInflater.from(context).inflate(R.layout.cell_saved_board, parent, false)); |
||||
} |
||||
|
||||
@Override |
||||
public void onBindViewHolder(SavedBoardCell holder, int position) { |
||||
SavedBoard savedBoard = savedBoards.get(position); |
||||
holder.setSavedBoard(savedBoard); |
||||
} |
||||
|
||||
@Override |
||||
public int getItemCount() { |
||||
return savedBoards.size(); |
||||
} |
||||
} |
||||
|
||||
private class SavedBoardCell extends RecyclerView.ViewHolder { |
||||
private ImageView image; |
||||
private TextView text; |
||||
|
||||
public SavedBoardCell(View itemView) { |
||||
super(itemView); |
||||
|
||||
image = (ImageView) itemView.findViewById(R.id.image); |
||||
text = (TextView) itemView.findViewById(R.id.text); |
||||
} |
||||
|
||||
public void setSavedBoard(SavedBoard savedBoard) { |
||||
Bitmap bitmap; |
||||
try { |
||||
BitmapFactory.Options opts = new BitmapFactory.Options(); |
||||
opts.inScaled = false; |
||||
bitmap = BitmapFactory.decodeStream(getAppContext().getAssets().open("icons/4chan.png"), null, opts); |
||||
} catch (IOException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
|
||||
BitmapDrawable drawable = new BitmapDrawable(getRes(), bitmap); |
||||
drawable = (BitmapDrawable) drawable.mutate(); |
||||
drawable.getPaint().setFilterBitmap(false); |
||||
|
||||
image.setImageDrawable(drawable); |
||||
text.setText(savedBoard.title); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,357 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program 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. |
||||
* |
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.ui.controller; |
||||
|
||||
|
||||
import android.animation.Animator; |
||||
import android.animation.AnimatorListenerAdapter; |
||||
import android.animation.AnimatorSet; |
||||
import android.animation.ArgbEvaluator; |
||||
import android.animation.ObjectAnimator; |
||||
import android.animation.ValueAnimator; |
||||
import android.annotation.TargetApi; |
||||
import android.content.Context; |
||||
import android.graphics.Color; |
||||
import android.graphics.Paint; |
||||
import android.graphics.Path; |
||||
import android.os.Build; |
||||
import android.support.v4.view.animation.PathInterpolatorCompat; |
||||
import android.support.v7.widget.LinearLayoutManager; |
||||
import android.support.v7.widget.RecyclerView; |
||||
import android.view.LayoutInflater; |
||||
import android.view.View; |
||||
import android.view.ViewGroup; |
||||
import android.view.ViewGroupOverlay; |
||||
import android.widget.Button; |
||||
import android.widget.EditText; |
||||
import android.widget.ImageView; |
||||
import android.widget.TextView; |
||||
|
||||
import org.floens.chan.R; |
||||
import org.floens.chan.controller.transition.FadeInTransition; |
||||
import org.floens.chan.core.presenter.SetupPresenter; |
||||
import org.floens.chan.ui.animation.AnimationUtils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import static org.floens.chan.utils.AndroidUtils.dp; |
||||
import static org.floens.chan.utils.AndroidUtils.getAttrColor; |
||||
|
||||
public class SiteSetupController extends StyledToolbarNavigationController implements View.OnClickListener, SetupPresenter.Callback { |
||||
private EditText url; |
||||
private View urlSubmit; |
||||
private View spinner; |
||||
private Button next; |
||||
|
||||
private boolean blocked = false; |
||||
|
||||
private SetupPresenter presenter; |
||||
|
||||
private RecyclerView sitesRecyclerview; |
||||
private SitesAdapter sitesAdapter; |
||||
private List<SetupPresenter.AddedSite> sites = new ArrayList<>(); |
||||
|
||||
public SiteSetupController(Context context) { |
||||
super(context); |
||||
} |
||||
|
||||
@Override |
||||
public void onCreate() { |
||||
super.onCreate(); |
||||
|
||||
view = inflateRes(R.layout.controller_site_setup); |
||||
navigationItem.setTitle(R.string.setup_title); |
||||
|
||||
url = (EditText) view.findViewById(R.id.site_url); |
||||
urlSubmit = view.findViewById(R.id.site_url_submit); |
||||
urlSubmit.setOnClickListener(this); |
||||
spinner = view.findViewById(R.id.progress); |
||||
sitesRecyclerview = (RecyclerView) view.findViewById(R.id.sites_recycler); |
||||
sitesRecyclerview.setLayoutManager(new LinearLayoutManager(context)); |
||||
next = (Button) view.findViewById(R.id.next_button); |
||||
next.setOnClickListener(this); |
||||
|
||||
presenter = new SetupPresenter(); |
||||
|
||||
sitesAdapter = new SitesAdapter(); |
||||
sitesRecyclerview.setAdapter(sitesAdapter); |
||||
|
||||
presenter.create(this); |
||||
} |
||||
|
||||
@Override |
||||
public void onClick(View v) { |
||||
if (blocked) return; |
||||
|
||||
if (v == urlSubmit) { |
||||
presenter.onUrlSubmitClicked(url.getText().toString()); |
||||
} else if (v == next) { |
||||
presenter.onNextClicked(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean onBack() { |
||||
if (presenter.mayExit()) { |
||||
return super.onBack(); |
||||
} else { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void moveToSavedBoards() { |
||||
navigationController.pushController(new BoardSetupController(context), new FadeInTransition()); |
||||
} |
||||
|
||||
@Override |
||||
public void goToUrlSubmittedState() { |
||||
spinner.setVisibility(View.VISIBLE); |
||||
urlSubmit.setVisibility(View.INVISIBLE); |
||||
} |
||||
|
||||
@Override |
||||
public void runSiteAddedAnimation(final SetupPresenter.AddedSite site) { |
||||
spinner.setVisibility(View.INVISIBLE); |
||||
urlSubmit.setVisibility(View.VISIBLE); |
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { |
||||
runSiteAddedAnimationInternal(site); |
||||
} else { |
||||
resetUrl(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void showUrlHint(String text) { |
||||
spinner.setVisibility(View.INVISIBLE); |
||||
urlSubmit.setVisibility(View.VISIBLE); |
||||
|
||||
url.setError(text, null); |
||||
} |
||||
|
||||
@Override |
||||
public void setAddedSites(List<SetupPresenter.AddedSite> sites) { |
||||
this.sites.clear(); |
||||
this.sites.addAll(sites); |
||||
sitesAdapter.notifyDataSetChanged(); |
||||
} |
||||
|
||||
@Override |
||||
public void setNextAllowed(boolean nextAllowed, boolean animate) { |
||||
next.setEnabled(nextAllowed); |
||||
int newBackground = getAttrColor(context, nextAllowed ? R.attr.colorAccent : R.attr.backcolor); |
||||
int newTextColor = nextAllowed ? Color.WHITE : getAttrColor(context, R.attr.text_color_hint); |
||||
if (animate) { |
||||
AnimationUtils.animateTextColor(next, newTextColor); |
||||
AnimationUtils.animateBackgroundColorDrawable(next, newBackground); |
||||
} else { |
||||
next.setBackgroundColor(newBackground); |
||||
next.setTextColor(newTextColor); |
||||
} |
||||
} |
||||
|
||||
private void resetUrl() { |
||||
url.setText(""); |
||||
} |
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) |
||||
private void runSiteAddedAnimationInternal(SetupPresenter.AddedSite site) { |
||||
blocked = true; |
||||
sitesAdapter.invisibleSiteOnBind = site; |
||||
|
||||
SiteCell siteCell = new SiteCell(LayoutInflater.from(context).inflate(R.layout.cell_site, null)); |
||||
siteCell.setSite(site); |
||||
final View siteCellView = siteCell.itemView; |
||||
final View siteCellIcon = siteCell.image; |
||||
siteCellView.measure(View.MeasureSpec.makeMeasureSpec(url.getMeasuredWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); |
||||
siteCellView.layout(0, 0, siteCellView.getMeasuredWidth(), siteCellView.getMeasuredHeight()); |
||||
|
||||
final ViewGroupOverlay overlay = view.getOverlay(); |
||||
|
||||
overlay.add(siteCellView); |
||||
|
||||
int[] urlWinLoc = new int[2]; |
||||
url.getLocationInWindow(urlWinLoc); |
||||
int[] recWinLoc = new int[2]; |
||||
sitesRecyclerview.getLocationInWindow(recWinLoc); |
||||
recWinLoc[0] += sitesRecyclerview.getPaddingLeft(); |
||||
recWinLoc[1] += sitesRecyclerview.getPaddingTop() + siteCellView.getMeasuredHeight() * (sites.size() - 1); |
||||
int[] viewWinLoc = new int[2]; |
||||
view.getLocationInWindow(viewWinLoc); |
||||
|
||||
String urlText = url.getText().toString(); |
||||
int indexOf = urlText.indexOf(site.title); |
||||
int offsetLeft = 0; |
||||
if (indexOf > 0) { |
||||
Paint paint = new Paint(); |
||||
paint.setTextSize(url.getTextSize()); |
||||
offsetLeft = (int) paint.measureText(urlText.substring(0, indexOf)); |
||||
} |
||||
|
||||
final int staX = urlWinLoc[0] - viewWinLoc[0] - dp(48) + dp(4) + offsetLeft; |
||||
final int staY = urlWinLoc[1] - viewWinLoc[1] - dp(4); |
||||
final int desX = recWinLoc[0] - viewWinLoc[0]; |
||||
final int desY = recWinLoc[1] - viewWinLoc[1]; |
||||
|
||||
siteCellView.setTranslationX(staX); |
||||
siteCellView.setTranslationY(staY); |
||||
|
||||
final int textColor = url.getCurrentTextColor(); |
||||
final int textHintColor = url.getCurrentHintTextColor(); |
||||
|
||||
ValueAnimator textAlpha = ValueAnimator.ofObject(new ArgbEvaluator(), |
||||
textColor, textColor & 0xffffff); |
||||
textAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
||||
@Override |
||||
public void onAnimationUpdate(ValueAnimator animation) { |
||||
url.setTextColor((int) animation.getAnimatedValue()); |
||||
} |
||||
}); |
||||
textAlpha.setDuration(300); |
||||
textAlpha.addListener(new AnimatorListenerAdapter() { |
||||
@Override |
||||
public void onAnimationEnd(Animator animation) { |
||||
resetUrl(); |
||||
} |
||||
}); |
||||
|
||||
url.setCursorVisible(false); |
||||
url.setHintTextColor(0); |
||||
|
||||
ValueAnimator alpha = ObjectAnimator.ofFloat(siteCellView, View.ALPHA, 0f, 1f); |
||||
alpha.setDuration(300); |
||||
|
||||
ValueAnimator iconAlpha = ValueAnimator.ofFloat(0f, 1f); |
||||
iconAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
||||
@Override |
||||
public void onAnimationUpdate(ValueAnimator animation) { |
||||
siteCellIcon.setAlpha((float) animation.getAnimatedValue()); |
||||
} |
||||
}); |
||||
iconAlpha.setDuration(400); |
||||
iconAlpha.setStartDelay(500); |
||||
siteCellIcon.setAlpha(0f); |
||||
|
||||
ValueAnimator horizontal = ValueAnimator.ofFloat(0f, 1f); |
||||
horizontal.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
||||
@Override |
||||
public void onAnimationUpdate(ValueAnimator animation) { |
||||
float value = (float) animation.getAnimatedValue(); |
||||
siteCellView.setTranslationX(staX + (desX - staX) * value); |
||||
} |
||||
}); |
||||
horizontal.setDuration(600); |
||||
horizontal.setStartDelay(400); |
||||
|
||||
ValueAnimator vertical = ValueAnimator.ofFloat(0f, 1f); |
||||
vertical.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
||||
@Override |
||||
public void onAnimationUpdate(ValueAnimator animation) { |
||||
float value = (float) animation.getAnimatedValue(); |
||||
siteCellView.setTranslationY(staY + (desY - staY) * value); |
||||
} |
||||
}); |
||||
|
||||
Path path = new Path(); |
||||
|
||||
float jump = 300f / Math.abs(desY - staY); |
||||
path.cubicTo(0.5f, 0f - jump, 0.75f, 1.0f, 1f, 1f); |
||||
vertical.setInterpolator(PathInterpolatorCompat.create(path)); |
||||
vertical.setDuration(600); |
||||
vertical.setStartDelay(400); |
||||
|
||||
ValueAnimator hintAlpha = ValueAnimator.ofObject(new ArgbEvaluator(), |
||||
textHintColor & 0xffffff, textHintColor); |
||||
hintAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
||||
@Override |
||||
public void onAnimationUpdate(ValueAnimator animation) { |
||||
url.setHintTextColor((int) animation.getAnimatedValue()); |
||||
} |
||||
}); |
||||
hintAlpha.setDuration(300); |
||||
hintAlpha.setStartDelay(1000); |
||||
|
||||
AnimatorSet set = new AnimatorSet(); |
||||
set.playTogether(alpha, textAlpha, iconAlpha, horizontal, vertical, hintAlpha); |
||||
set.addListener(new AnimatorListenerAdapter() { |
||||
@Override |
||||
public void onAnimationEnd(Animator animation) { |
||||
blocked = false; |
||||
overlay.remove(siteCellView); |
||||
sitesAdapter.invisibleSiteOnBind = null; |
||||
for (int i = 0; i < sitesRecyclerview.getChildCount(); i++) { |
||||
sitesRecyclerview.getChildAt(i).setVisibility(View.VISIBLE); |
||||
} |
||||
url.setTextColor(textColor); |
||||
url.setHintTextColor(textHintColor); |
||||
url.setCursorVisible(true); |
||||
} |
||||
}); |
||||
set.start(); |
||||
} |
||||
|
||||
private class SitesAdapter extends RecyclerView.Adapter<SiteCell> { |
||||
private SetupPresenter.AddedSite invisibleSiteOnBind; |
||||
|
||||
public SitesAdapter() { |
||||
setHasStableIds(true); |
||||
} |
||||
|
||||
@Override |
||||
public long getItemId(int position) { |
||||
return sites.get(position).id; |
||||
} |
||||
|
||||
@Override |
||||
public SiteCell onCreateViewHolder(ViewGroup parent, int viewType) { |
||||
return new SiteCell(LayoutInflater.from(context).inflate(R.layout.cell_site, parent, false)); |
||||
} |
||||
|
||||
@Override |
||||
public void onBindViewHolder(SiteCell holder, int position) { |
||||
SetupPresenter.AddedSite site = sites.get(position); |
||||
holder.setSite(site); |
||||
if (site == invisibleSiteOnBind) { |
||||
holder.itemView.setVisibility(View.INVISIBLE); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int getItemCount() { |
||||
return sites.size(); |
||||
} |
||||
} |
||||
|
||||
private class SiteCell extends RecyclerView.ViewHolder { |
||||
private ImageView image; |
||||
private TextView text; |
||||
|
||||
public SiteCell(View itemView) { |
||||
super(itemView); |
||||
image = (ImageView) itemView.findViewById(R.id.image); |
||||
text = (TextView) itemView.findViewById(R.id.text); |
||||
} |
||||
|
||||
private void setSite(SetupPresenter.AddedSite site) { |
||||
image.setImageDrawable(site.drawable); |
||||
text.setText(site.title); |
||||
} |
||||
} |
||||
} |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 147 B |
After Width: | Height: | Size: 149 B |
After Width: | Height: | Size: 151 B |
After Width: | Height: | Size: 86 B |
After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 125 B |
After Width: | Height: | Size: 108 B |
After Width: | Height: | Size: 150 B |
After Width: | Height: | Size: 171 B |
After Width: | Height: | Size: 168 B |
After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 186 B |
After Width: | Height: | Size: 213 B |
After Width: | Height: | Size: 215 B |
After Width: | Height: | Size: 119 B |
After Width: | Height: | Size: 222 B |
After Width: | Height: | Size: 261 B |
After Width: | Height: | Size: 256 B |
@ -0,0 +1,42 @@ |
||||
<?xml version="1.0" encoding="utf-8"?><!-- |
||||
Clover - 4chan browser https://github.com/Floens/Clover/ |
||||
Copyright (C) 2014 Floens |
||||
|
||||
This program 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. |
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. |
||||
--> |
||||
<LinearLayout |
||||
xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="48dp" |
||||
android:background="?attr/backcolor" |
||||
android:orientation="horizontal"> |
||||
|
||||
<ImageView |
||||
android:id="@+id/image" |
||||
android:layout_width="48dp" |
||||
android:layout_height="48dp" |
||||
android:padding="8dp" |
||||
android:scaleType="fitCenter"/> |
||||
|
||||
<TextView |
||||
android:id="@+id/text" |
||||
android:layout_width="0dp" |
||||
android:layout_height="48dp" |
||||
android:layout_weight="1" |
||||
android:gravity="center_vertical" |
||||
android:maxLines="1" |
||||
android:textColor="?text_color_primary" |
||||
android:textSize="14sp"/> |
||||
|
||||
</LinearLayout> |
@ -0,0 +1,41 @@ |
||||
<?xml version="1.0" encoding="utf-8"?><!-- |
||||
Clover - 4chan browser https://github.com/Floens/Clover/ |
||||
Copyright (C) 2014 Floens |
||||
|
||||
This program 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. |
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. |
||||
--> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="48dp" |
||||
android:background="?selectableItemBackground" |
||||
android:orientation="horizontal"> |
||||
|
||||
<ImageView |
||||
android:id="@+id/image" |
||||
android:layout_width="48dp" |
||||
android:layout_height="48dp" |
||||
android:padding="8dp" |
||||
android:scaleType="fitCenter" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/text" |
||||
android:layout_width="0dp" |
||||
android:layout_height="48dp" |
||||
android:layout_weight="1" |
||||
android:gravity="center_vertical" |
||||
android:maxLines="1" |
||||
android:textColor="?text_color_primary" |
||||
android:textSize="14sp" /> |
||||
|
||||
</LinearLayout> |
@ -0,0 +1,83 @@ |
||||
<?xml version="1.0" encoding="utf-8"?><!-- |
||||
Clover - 4chan browser https://github.com/Floens/Clover/ |
||||
Copyright (C) 2014 Floens |
||||
|
||||
This program 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. |
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. |
||||
--> |
||||
<android.support.constraint.ConstraintLayout |
||||
xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:background="?attr/backcolor"> |
||||
|
||||
<TextView |
||||
android:id="@+id/introduction" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginEnd="8dp" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginRight="8dp" |
||||
android:layout_marginStart="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:text="@string/saved_boards_introduction" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent"/> |
||||
|
||||
<TextView |
||||
android:id="@+id/code_hint" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="0dp" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginStart="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:gravity="center_vertical" |
||||
android:text="@string/saved_boards_code" |
||||
app:layout_constraintBottom_toBottomOf="@+id/code" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/introduction"/> |
||||
|
||||
<AutoCompleteTextView |
||||
android:id="@+id/code" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginEnd="8dp" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginRight="8dp" |
||||
android:layout_marginStart="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:ems="10" |
||||
android:hint="@string/saved_boards_code_hint" |
||||
android:inputType="textPersonName" |
||||
android:textSize="14sp" |
||||
app:layout_constraintHorizontal_bias="0.0" |
||||
app:layout_constraintLeft_toRightOf="@+id/code_hint" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/introduction"/> |
||||
|
||||
<android.support.v7.widget.RecyclerView |
||||
android:id="@+id/boards_recycler" |
||||
android:layout_width="0dp" |
||||
android:layout_height="0dp" |
||||
android:layout_marginBottom="8dp" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginRight="8dp" |
||||
android:layout_marginTop="0dp" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/code"/> |
||||
|
||||
</android.support.constraint.ConstraintLayout> |
@ -0,0 +1,150 @@ |
||||
<?xml version="1.0" encoding="utf-8"?><!-- |
||||
Clover - 4chan browser https://github.com/Floens/Clover/ |
||||
Copyright (C) 2014 Floens |
||||
|
||||
This program 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. |
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. |
||||
--> |
||||
<android.support.constraint.ConstraintLayout |
||||
xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
xmlns:tools="http://schemas.android.com/tools" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:animateLayoutChanges="true" |
||||
android:background="?attr/backcolor" |
||||
tools:ignore="ContentDescription,RtlHardcoded"> |
||||
|
||||
<TextView |
||||
android:id="@+id/introduction" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginEnd="8dp" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginRight="8dp" |
||||
android:layout_marginStart="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:text="@string/setup_introduction" |
||||
app:layout_constraintHorizontal_bias="0.0" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent"/> |
||||
|
||||
<EditText |
||||
android:id="@+id/site_url" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginEnd="8dp" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginRight="8dp" |
||||
android:layout_marginStart="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:hint="@string/setup_site_url_hint" |
||||
android:inputType="textUri" |
||||
android:textSize="14sp" |
||||
app:layout_constraintHorizontal_bias="0.0" |
||||
app:layout_constraintLeft_toRightOf="@+id/site_url_label" |
||||
app:layout_constraintRight_toLeftOf="@+id/site_url_submit" |
||||
app:layout_constraintTop_toBottomOf="@+id/introduction"/> |
||||
|
||||
<ImageButton |
||||
android:id="@+id/site_url_submit" |
||||
android:layout_width="0dp" |
||||
android:layout_height="0dp" |
||||
android:layout_marginEnd="7dp" |
||||
android:layout_marginRight="7dp" |
||||
android:layout_marginTop="8dp" |
||||
android:background="?selectableItemBackground" |
||||
app:layout_constraintBottom_toBottomOf="@+id/site_url" |
||||
app:layout_constraintDimensionRatio="w,1:1" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/introduction" |
||||
app:layout_constraintVertical_bias="0.0" |
||||
app:srcCompat="@drawable/ic_add_black_24dp"/> |
||||
|
||||
<ProgressBar |
||||
android:id="@+id/progress" |
||||
android:layout_width="0dp" |
||||
android:layout_height="0dp" |
||||
android:layout_marginEnd="8dp" |
||||
android:layout_marginRight="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:padding="8dp" |
||||
android:visibility="invisible" |
||||
app:layout_constraintBottom_toBottomOf="@+id/site_url" |
||||
app:layout_constraintDimensionRatio="w,1:1" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/introduction"/> |
||||
|
||||
<TextView |
||||
android:id="@+id/site_url_label" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="0dp" |
||||
android:layout_marginBottom="0dp" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginStart="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:gravity="center" |
||||
android:text="@string/setup_site_url" |
||||
app:layout_constraintBottom_toBottomOf="@+id/site_url" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/introduction" |
||||
app:layout_constraintVertical_bias="0.0"/> |
||||
|
||||
<android.support.v7.widget.RecyclerView |
||||
android:id="@+id/sites_recycler" |
||||
android:layout_width="0dp" |
||||
android:layout_height="0dp" |
||||
android:layout_marginBottom="0dp" |
||||
android:layout_marginLeft="0dp" |
||||
android:layout_marginRight="0dp" |
||||
android:layout_marginTop="0dp" |
||||
android:padding="8dp" |
||||
android:scrollbarStyle="outsideOverlay" |
||||
android:scrollbars="vertical" |
||||
app:layout_constraintBottom_toTopOf="@+id/next_button" |
||||
app:layout_constraintHorizontal_bias="0.0" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/divider"/> |
||||
|
||||
<View |
||||
android:id="@+id/divider" |
||||
android:layout_width="0dp" |
||||
android:layout_height="1dp" |
||||
android:layout_marginLeft="0dp" |
||||
android:layout_marginRight="0dp" |
||||
android:layout_marginTop="8dp" |
||||
android:background="?attr/divider_color" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/site_url"/> |
||||
|
||||
<Button |
||||
android:id="@+id/next_button" |
||||
style="@style/Widget.AppCompat.Button.Borderless" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginBottom="0dp" |
||||
android:layout_marginLeft="0dp" |
||||
android:layout_marginRight="0dp" |
||||
android:background="@android:color/white" |
||||
android:elevation="12dp" |
||||
android:foreground="?selectableItemBackground" |
||||
android:text="@string/next" |
||||
android:textColor="?text_color_hint" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent"/> |
||||
|
||||
</android.support.constraint.ConstraintLayout> |
@ -0,0 +1 @@ |
||||
org.gradle.jvmargs=-Xmx2048M |