summaryrefslogtreecommitdiffstats
path: root/src/com/android/calendar/ShareCalendarActivity.java
blob: cd538ca6f4cd5ad4979a6abde754d9f15d09799e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package com.android.calendar;

import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.calendar.agenda.AgendaFragment;
import com.android.calendar.icalendar.IcalendarUtils;
import com.android.calendar.icalendar.VCalendar;
import com.android.calendar.icalendar.VEvent;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;

/**
 * Handles requests for sharing calendar events
 * This activity returns a vcs formatted file
 */
public class ShareCalendarActivity extends Activity implements CalendarUtils.ShareEventListener {

    public static final String EXTRA_LIMIT_TO_ONE_EVENT = "EXTRA_LIMIT_TO_ONE_EVENT";

    private static final String TAG = "ShareCalendarActivity";

    private HashSet<CalendarUtils.Triple<Long, Long, Long>> mShareEventsList =
            new HashSet<CalendarUtils.Triple<Long, Long, Long>>();

    private ArrayList<EventInfoFragment> mEventDataFragments = new ArrayList<EventInfoFragment>();

    private ActionBar mActionBar;
    private AgendaFragment mAgendaFragment;
    private long mStartMillis;
    private ArrayList<Uri> mFileUris = new ArrayList<Uri>();
    private int mNumQueriesCompleted;
    private boolean mShouldSelectSingleEvent;
    private Resources mResources;
    private String mNoSelectionMsg;

    @Override
    public void onEventShared(CalendarUtils.Triple<Long, Long, Long> eventInfo) {
        if (eventInfo.first < 0) return;

        mShareEventsList.add(eventInfo);
        updateSubtitle();
    }

    @Override
    public void onEventRemoval(long eventId) {
        if (eventId < 0) return;

        CalendarUtils.Triple<Long, Long, Long> eventInfo =
                new CalendarUtils.Triple<Long, Long, Long>(eventId, 0l, 0l);
        mShareEventsList.remove(eventInfo);
        updateSubtitle();
    }

    @Override
    public void onResetShareList() {
        // undo
        mShareEventsList.clear();
        updateSubtitle();
    }

    public void updateSubtitle() {
        int listSize = mShareEventsList.size();
        String subtitle;
        // workaround for Android's poor pluralization treatment of 'zero' quantity in English
        if (listSize == 0) {
            subtitle = mNoSelectionMsg;
        } else {
            subtitle = mResources.getQuantityString(R.plurals.events_selected,
                    listSize, listSize);
        }
        mActionBar.setSubtitle(subtitle);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        Bundle args = intent.getExtras();
        if (args != null) {
            mShouldSelectSingleEvent = args.getBoolean(EXTRA_LIMIT_TO_ONE_EVENT, false);
        }

        mStartMillis = System.currentTimeMillis();
        setContentView(R.layout.simple_frame_layout);
        mResources = getResources();

        // create agenda fragment displaying the list of calendar events
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction ft = fragmentManager.beginTransaction();
        mAgendaFragment = new AgendaFragment(mStartMillis, false, true);
        mAgendaFragment.setShareModeOptions(this, mShouldSelectSingleEvent);
        ft.replace(R.id.main_frame, mAgendaFragment);
        ft.commit();

        mActionBar = getActionBar();
        mActionBar.setDisplayShowTitleEnabled(true);
        String title = mShouldSelectSingleEvent ?
                mResources.getQuantityString(R.plurals.select_events_to_share, 1) :
                mResources.getQuantityString(R.plurals.select_events_to_share, 2) ;

        mActionBar.setTitle(title);
        mNoSelectionMsg = mResources.getString(R.string.no_events_selected);
        updateSubtitle();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.share_event_title_bar, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            case(R.id.action_done):
                generateEventData();
                evalIfComplete();
                break;

            case (R.id.action_cancel):
                setResultAndFinish(false);
                break;

        }
        return super.onOptionsItemSelected(item);
    }

    // called after the data fragment's is done loading
    public void queryComplete() {
        mNumQueriesCompleted++;
        evalIfComplete();
    }

    // used load event information for the list of selected events
    private void generateEventData() {
        for (CalendarUtils.Triple<Long, Long, Long> event : mShareEventsList) {

            long eventId = event.first;
            long eventStartMillis = event.second;
            long eventEndMillis = event.third;

            // EventInfoFragment just serves as a data fragment and is initialized with
            // default arguments for parameters that don't affect model loading
            EventInfoFragment eif = new EventInfoFragment(this, eventId, eventStartMillis,
                    eventEndMillis, CalendarContract.Attendees.ATTENDEE_STATUS_NONE, false, 0,
                    null);
            eif.launchInNonUiMode();
            eif.startQueryingData(this);
            eif.setQueryCompleteRunnable(new Runnable() {
                @Override
                public void run() {
                    // indicate model loading is complete
                    queryComplete();
                }
            });

            mEventDataFragments.add(eif);
        }

    }

    // generates the vcs files if the data for selected events has been successfully queried
    private void evalIfComplete() {
        if (mNumQueriesCompleted != 0 && mNumQueriesCompleted == mEventDataFragments.size()) {

            for(EventInfoFragment event : mEventDataFragments) {
                try {
                    // generate vcs file
                    VCalendar calendar = event.generateVCalendar();
                    // event title serves as the file name prefix
                    String filePrefix = calendar.getFirstEvent().getProperty(VEvent.SUMMARY);
                    if (filePrefix == null || filePrefix.length() < 3) {
                        // default to a generic filename if event title doesn't qualify
                        // prefix length constraint is imposed by File#createTempFile
                        filePrefix = "invite";
                    }

                    filePrefix = filePrefix.replaceAll("\\W+", " ");

                    if (!filePrefix.endsWith(" ")) {
                        filePrefix += " ";
                    }
                    File dir = getExternalCacheDir();
                    File inviteFile = IcalendarUtils.createTempFile(filePrefix, ".vcs", dir);
                    inviteFile.setReadable(true, false);     // set world-readable
                    if (IcalendarUtils.writeCalendarToFile(calendar, inviteFile)) {
                        mFileUris.add(Uri.fromFile(inviteFile));
                    }
                } catch (IOException ioe) {
                    break;
                }
            }

            setResultAndFinish(true);

        } else if (mEventDataFragments.size() < 1) {    // if no events have been selected
            setResultAndFinish(false);
        }
    }

    private void setResultAndFinish(boolean isResultAvailable) {
        if (isResultAvailable) {
            Intent intent = new Intent();
            intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, mFileUris);
            setResult(RESULT_OK, intent);
            finish();
        } else {
            setResult(RESULT_CANCELED);
            finish();
        }
    }
}