]> Pileus Git - ~andy/freeotp/blob - src/org/fedorahosted/freeotp/TokenAdapter.java
b0035e5cef5dd704e00454520e27fb5aaf70fdde
[~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  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 package org.fedorahosted.freeotp;
22
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import org.fedorahosted.freeotp.Token.TokenUriInvalidException;
27
28 import android.app.AlertDialog;
29 import android.content.Context;
30 import android.content.DialogInterface;
31 import android.os.Handler;
32 import android.os.Message;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.view.View.OnClickListener;
36 import android.view.ViewGroup;
37 import android.widget.BaseAdapter;
38 import android.widget.ImageButton;
39 import android.widget.ProgressBar;
40 import android.widget.TextView;
41
42 public class TokenAdapter extends BaseAdapter {
43         private static class Ticker extends Handler {
44                 private static interface OnTickListener {
45                         public void tick(ProgressBar pb);
46                 }
47
48                 private final Map<ProgressBar, OnTickListener> map = new HashMap<ProgressBar, OnTickListener>();
49
50                 @Override
51                 public void handleMessage(Message msg) {
52                         for (ProgressBar pb : map.keySet())
53                                 map.get(pb).tick(pb);
54
55                         sendEmptyMessageDelayed(0, 200);
56                 }
57
58                 public void set(ProgressBar pb, OnTickListener otl) {
59                         map.put(pb, otl);
60                 }
61         }
62
63         private static class ViewHolder {
64                 int index;
65                 Token token;
66                 TextView code;
67                 TextView title;
68         }
69
70         private final TokenStore ts;
71         private final Ticker ticker = new Ticker();
72
73         public TokenAdapter(Context ctx) {
74                 ts = new TokenStore(ctx);
75                 ticker.sendEmptyMessageDelayed(0, 200);
76         }
77
78         @Override
79         public int getCount() {
80                 return ts.getTokenCount();
81         }
82
83         @Override
84         public Token getItem(int position) {
85                 return ts.get(position);
86         }
87
88         @Override
89         public long getItemId(int position) {
90                 return position;
91         }
92
93         @Override
94         public View getView(int position, View convertView, ViewGroup parent) {
95                 Token token = ts.get(position);
96
97         if (convertView == null)
98             convertView = newView(parent.getContext(), token.getType(), parent);
99
100         bindView(parent.getContext(), convertView, token, position);
101         return convertView;
102         }
103
104         public void bindView(Context ctx, View view, Token token, int position) {
105                 ViewHolder holder = (ViewHolder) view.getTag();
106                 holder.index = position;
107                 holder.token = token;
108
109                 holder.code.setText(token.getPlaceholder());
110                 holder.title.setText(token.getIssuer() + ": " + token.getLabel());
111         }
112
113         public View newView(Context ctx, Token.TokenType type, ViewGroup parent) {
114                 LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
115                 ViewHolder holder = new ViewHolder();
116
117                 View view = null;
118                 switch (type) {
119                 case HOTP:
120                         view = inflater.inflate(R.layout.hotp, parent, false);
121                         ImageButton hotp = (ImageButton) view.findViewById(R.id.hotpButton);
122                         hotp.setTag(holder);
123                         hotp.setOnClickListener(new OnClickListener() {
124                                 @Override
125                                 public void onClick(View v) {
126                                         ViewHolder holder = (ViewHolder) v.getTag();
127                                         holder.code.setText(holder.token.getCode());
128                                         holder.token.increment();
129                                         ts.save(holder.token);
130                                 }
131                         });
132                         break;
133
134                 case TOTP:
135                         view = inflater.inflate(R.layout.totp, parent, false);
136                         ProgressBar pb = (ProgressBar) view.findViewById(R.id.totpProgressBar);
137                         pb.setTag(holder);
138                         ticker.set(pb, new Ticker.OnTickListener() {
139                                 @Override
140                                 public void tick(ProgressBar pb) {
141                                         ViewHolder holder = (ViewHolder) pb.getTag();
142                                         pb.setProgress(pb.getMax() - holder.token.getProgress());
143                                         holder.code.setText(holder.token.getCode());
144                                 }
145                         });
146                         break;
147                 }
148
149                 ImageButton ib = (ImageButton) view.findViewById(R.id.button);
150                 ib.setTag(holder);
151                 ib.setOnClickListener(new OnClickListener() {
152                         @Override
153                         public void onClick(View v) {
154                                 final ViewHolder holder = (ViewHolder) v.getTag();
155
156                                 StringBuilder sb = new StringBuilder();
157                                 sb.append(v.getContext().getString(R.string.delete_message));
158                                 sb.append(holder.token.getIssuer());
159                                 sb.append("\n");
160                                 sb.append(holder.token.getLabel());
161
162                                 AlertDialog ad = new AlertDialog.Builder(v.getContext())
163                                         .setTitle("Delete")
164                                         .setMessage(sb.toString())
165                                         .setIcon(android.R.drawable.ic_delete)
166                                         .setPositiveButton(R.string.delete,
167                                                         new DialogInterface.OnClickListener() {
168                                                                 @Override
169                                                                 public void onClick(DialogInterface dialog, int which) {
170                                                                         ts.del(holder.index);
171                                                                         notifyDataSetChanged();
172                                                                         dialog.dismiss();
173                                                                 }
174
175                                                         })
176                                         .setNegativeButton(android.R.string.cancel,
177                                                         new DialogInterface.OnClickListener() {
178                                                                 @Override
179                                                                 public void onClick(DialogInterface dialog, int which) {
180                                                                         dialog.cancel();
181                                                                 }
182                                                         })
183                                         .create();
184                                 ad.show();
185                         }
186                 });
187
188                 holder.code = (TextView) view.findViewById(R.id.code);
189                 holder.title = (TextView) view.findViewById(R.id.title);
190                 view.setTag(holder);
191
192                 return view;
193         }
194
195         @Override
196         public int getViewTypeCount() {
197                 return 2;
198         }
199
200         @Override
201         public int getItemViewType(int position) {
202                 switch (getItem(position).getType()) {
203                 case HOTP:
204                         return 0;
205                 case TOTP:
206                         return 1;
207                 default:
208                         return IGNORE_ITEM_VIEW_TYPE;
209                 }
210         }
211
212         public void add(Context ctx, String uri) throws TokenUriInvalidException {
213                 ts.add(new Token(uri));
214                 notifyDataSetChanged();
215         }
216 }