]> Pileus Git - ~andy/freeotp/blob - src/org/fedorahosted/freeotp/TokenAdapter.java
06a3f3bbc0c7859fe072e68b3d7b7a45eb6e2131
[~andy/freeotp] / src / org / fedorahosted / freeotp / TokenAdapter.java
1 /*
2  * FreeOTP
3  *
4  * Authors: Nathaniel McCallum <npmccallum@redhat.com>
5  *
6  * Copyright (C) 2013  Nathaniel McCallum, Red Hat
7  * see file 'COPYING' for use and warranty information
8  *
9  * This program is free software you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 package org.fedorahosted.freeotp;
24
25 import java.security.NoSuchAlgorithmException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Comparator;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32
33 import org.fedorahosted.freeotp.Token.TokenUriInvalidException;
34
35 import android.app.AlertDialog;
36 import android.content.Context;
37 import android.content.DialogInterface;
38 import android.os.Handler;
39 import android.os.Message;
40 import android.view.View;
41 import android.view.View.OnClickListener;
42 import android.view.ViewGroup;
43 import android.widget.BaseAdapter;
44 import android.widget.ImageButton;
45 import android.widget.ProgressBar;
46 import android.widget.TextView;
47
48 public class TokenAdapter extends BaseAdapter {
49         private static class Ticker extends Handler {
50                 private static interface OnTickListener {
51                         public void tick(ProgressBar pb);
52                 }
53                 
54                 private Map<ProgressBar, OnTickListener> map = new HashMap<ProgressBar, OnTickListener>();
55                 
56                 @Override
57                 public void handleMessage(Message msg) {
58                         for (ProgressBar pb : map.keySet())
59                                 map.get(pb).tick(pb);
60                         
61                         sendEmptyMessageDelayed(0, 200);
62                 }
63                 
64                 public void set(ProgressBar pb, OnTickListener otl) {
65                         map.put(pb, otl);
66                 }
67         }
68         
69         private List<Token> tokens = new ArrayList<Token>();
70         private Ticker ticker = new Ticker();
71         
72         private void sort() {
73                 Collections.sort(tokens, new Comparator<Token>() {
74                         public int compare(Token lhs, Token rhs) {
75                                 return lhs.getTitle().compareTo(rhs.getTitle());
76                         }
77                 });
78         }
79         
80         public TokenAdapter(Context ctx) {
81                 tokens.addAll(Token.getTokens(ctx));
82                 ticker.sendEmptyMessageDelayed(0, 200);
83                 sort();
84         }
85         
86         @Override
87         public int getCount() {
88                 return tokens.size();
89         }
90
91         @Override
92         public Token getItem(int position) {
93                 return tokens.get(position);
94         }
95
96         @Override
97         public long getItemId(int position) {
98                 return position;
99         }
100
101         @Override
102         public View getView(int position, View convertView, ViewGroup parent) {
103                 final Context ctx = parent.getContext();
104                 
105                 if (convertView == null) {
106                         switch (getItem(position).getType()) {
107                         case HOTP:
108                                 convertView = View.inflate(ctx, R.layout.hotp, null);
109                                 break;
110                                 
111                         case TOTP:
112                                 convertView = View.inflate(ctx, R.layout.totp, null);
113                                 break;
114                         }
115                 }
116                 
117                 final Token item = getItem(position);
118                 final TextView code = (TextView) convertView.findViewById(R.id.code);
119                 final TextView title = (TextView) convertView.findViewById(R.id.title);
120                 final ImageButton ib = (ImageButton) convertView.findViewById(R.id.button);
121                 
122                 code.setText(item.getCurrentTokenValue(ctx, false));
123                 title.setText(item.getTitle());
124                 
125                 ib.setOnClickListener(new OnClickListener() {
126                         public void onClick(View v) {
127                                 String delmsg = ctx.getString(R.string.delete_message);
128
129                                 AlertDialog ad = new AlertDialog.Builder(ctx)
130                                 .setTitle("Delete")
131                                 .setMessage(delmsg + item.getTitle())
132                                 .setIcon(android.R.drawable.ic_delete)
133                                 .setPositiveButton(R.string.delete,
134                                                 new DialogInterface.OnClickListener() {
135                                                         public void onClick(DialogInterface dialog, int which) {
136                                                                 tokens.remove(tokens.indexOf(item));
137                                                                 item.remove(ctx);
138                                                                 notifyDataSetChanged();
139                                                                 dialog.dismiss();
140                                                         }
141         
142                                                 })
143                                 .setNegativeButton(android.R.string.cancel,
144                                                 new DialogInterface.OnClickListener() {
145                                                         public void onClick(DialogInterface dialog, int which) {
146                                                                 dialog.cancel();
147                                                         }
148                                                 }).create();
149                                 ad.show();
150                         }
151                 });
152
153                 switch (getItem(position).getType()) {
154                 case HOTP:
155                         ImageButton hotp = (ImageButton) convertView.findViewById(R.id.hotpButton);
156                         hotp.setOnClickListener(new OnClickListener() {
157                                 public void onClick(View v) {
158                                         code.setText(item.getCurrentTokenValue(ctx, true));
159                                 }
160                         });
161                         break;
162                         
163                 case TOTP:
164                         ProgressBar pb = (ProgressBar) convertView.findViewById(R.id.totpProgressBar);
165                         ticker.set(pb, new Ticker.OnTickListener() {
166                                 public void tick(ProgressBar pb) {
167                                         int max = pb.getMax();
168                                         int pro = item.getProgress();
169                                         pb.setProgress(max - pro);
170                                         if (pro < max / 20 || pro > max / 20 * 19)
171                                                 code.setText(item.getCurrentTokenValue(ctx, false));
172                                 }
173                         });
174                         break;
175                 }
176                 
177                 return convertView;
178         }
179         
180         @Override
181         public int getViewTypeCount() {
182                 return 2;
183         }
184         
185         @Override
186         public int getItemViewType(int position) {
187                 switch (getItem(position).getType()) {
188                 case HOTP:
189                         return 0;
190                 case TOTP:
191                         return 1;
192                 default:
193                         return -1;
194                 }
195         }
196         
197         public void add(Context ctx, String uri) throws NoSuchAlgorithmException, TokenUriInvalidException {
198                 Token t = new Token(uri);
199                 t.save(ctx);
200                 tokens.add(t);
201                 sort();
202                 notifyDataSetChanged();
203         }
204 }