Document.get().getElementById("savedStateContainer"));
final AjaxRpc rpc = new AjaxRpc("", indicator);
final boolean isLive;
final boolean useUdw;
@Nullable final UdwLoadData udwData;
final int randomSeed;
final String userIdString;
final boolean haveOAuthToken;
final String convObjectIdString;
final WaveletDiffSnapshot convSnapshot;
@Nullable final ConnectResponse convConnectResponse;
if (clientVars.hasStaticClientVars()) {
isLive = false;
StaticClientVars vars = clientVars.getStaticClientVars();
randomSeed = vars.getRandomSeed();
userIdString = vars.getUserEmail();
haveOAuthToken = vars.getHaveOauthToken();
convObjectIdString = vars.getConvObjectId();
convSnapshot = vars.getConvSnapshot();
convConnectResponse = null;
useUdw = false;
udwData = null;
} else {
isLive = true;
LiveClientVars vars = clientVars.getLiveClientVars();
randomSeed = vars.getRandomSeed();
userIdString = vars.getUserEmail();
haveOAuthToken = vars.getHaveOauthToken();
convObjectIdString =
vars.getConvConnectResponse().getSignedSession().getSession().getObjectId();
convSnapshot = vars.getConvSnapshot();
convConnectResponse = vars.getConvConnectResponse();
if (!vars.hasUdw()) {
useUdw = false;
udwData = null;
} else {
useUdw = true;
udwData = vars.getUdw();
udwObjectId = new SlobId(vars.getUdw().getConnectResponse()
.getSignedSession().getSession().getObjectId());
}
VersionChecker versionChecker = new VersionChecker(rpc, vars.getClientVersion());
// NOTE(danilatos): Use the highest priority timer, since we can't afford to
// let it be starved due to some bug with another non-terminating
// high-priority task. This task runs infrequently and is very minimal so
// the risk of impacting the UI is low.
SchedulerInstance.getHighPriorityTimer().scheduleRepeating(versionChecker,
VERSION_CHECK_INTERVAL_MS, VERSION_CHECK_INTERVAL_MS);
}
final RandomProviderImpl random =
// TODO(ohler): Get a stronger RandomProvider.
RandomProviderImpl.ofSeed(randomSeed);
final RandomBase64Generator random64 = new RandomBase64Generator(new RandomProvider() {
@Override public int nextInt(int upperBound) {
return random.nextInt(upperBound);
}});
final ParticipantId userId;
try {
userId = ParticipantId.of(userIdString);
} catch (InvalidParticipantAddress e1) {
Window.alert("Invalid user id received from server: " + userIdString);
return;
}
convObjectId = new SlobId(convObjectIdString);
idGenerator = new IdHack.MinimalIdGenerator(
IdHack.convWaveletIdFromObjectId(convObjectId),
useUdw ? IdHack.udwWaveletIdFromObjectId(udwObjectId)
// Some code depends on this not to return null, so let's return
// something.
: IdHack.DISABLED_UDW_ID,
random64);
// TODO(ohler): Make the server's response to the contacts RPC indicate
// whether an OAuth token is needed, and enable the button dynamically when
// appropriate, rather than statically.
UIObject.setVisible(Document.get().getElementById("enableAvatarsButton"),
!haveOAuthToken);
@Nullable final LoadWaveService loadWaveService = isLive ? new LoadWaveService(rpc) : null;
@Nullable final ChannelConnectService channelService =
isLive ? new ChannelConnectService(rpc) : null;
new Stages() {
@Override
protected AsyncHolder<StageZero> createStageZeroLoader() {
return new StageZero.DefaultProvider() {
@Override
protected UncaughtExceptionHandler createUncaughtExceptionHandler() {
return WalkaroundUncaughtExceptionHandler.INSTANCE;
}
};
}
@Override
protected AsyncHolder<StageOne> createStageOneLoader(StageZero zero) {
return new StageOne.DefaultProvider(zero) {
protected final ParticipantViewImpl.Helper<ParticipantAvatarDomImpl> participantHelper =
new ParticipantViewImpl.Helper<ParticipantAvatarDomImpl>() {
@Override public void remove(ParticipantAvatarDomImpl impl) {
impl.remove();
}
@Override public ProfilePopupView showParticipation(ParticipantAvatarDomImpl impl) {
return new ProfilePopupWidget(impl.getElement(),
AlignedPopupPositioner.BELOW_RIGHT);
}
};
@Override protected UpgradeableDomAsViewProvider createViewProvider() {
return new FullStructure(createCssProvider()) {
@Override public ParticipantView asParticipant(Element e) {
return e == null ? null : new ParticipantViewImpl<ParticipantAvatarDomImpl>(
participantHelper, ParticipantAvatarDomImpl.of(e));
}
};
}
};
}
@Override
protected AsyncHolder<StageTwo> createStageTwoLoader(final StageOne one) {
return new StageTwo.DefaultProvider(one, null) {
WaveViewData waveData;
StringMap<DocOp> diffMap = CollectionUtils.createStringMap();
@Override protected DomRenderer createRenderer() {
final BlipQueueRenderer pager = getBlipQueue();
DocRefRenderer docRenderer = new DocRefRenderer() {
@Override
public UiBuilder render(
ConversationBlip blip, IdentityMap<ConversationThread, UiBuilder> replies) {
// Documents are rendered blank, and filled in later when
// they get paged in.
pager.add(blip);
return DocRefRenderer.EMPTY.render(blip, replies);
}
};
RenderingRules<UiBuilder> rules = new MyFullDomRenderer(
getBlipDetailer(), docRenderer, getProfileManager(),
getViewIdMapper(), createViewFactories(), getThreadReadStateMonitor()) {
@Override
public UiBuilder render(Conversation conversation, ParticipantId participant) {
// Same as super class, but using avatars instead of names.
Profile profile = getProfileManager().getProfile(participant);
String id = getViewIdMapper().participantOf(conversation, participant);
ParticipantAvatarViewBuilder participantUi =
ParticipantAvatarViewBuilder.create(id);
participantUi.setAvatar(profile.getImageUrl());
participantUi.setName(profile.getFullName());
return participantUi;
}
};
return new HtmlDomRenderer(ReductionBasedRenderer.of(rules, getConversations()));
}
@Override
protected ProfileManager createProfileManager() {
return ContactsManager.create(rpc);
}
@Override
protected void create(final Accessor<StageTwo> whenReady) {
super.create(whenReady);
}
@Override
protected IdGenerator createIdGenerator() {
return idGenerator;
}
@Override
protected void fetchWave(final Accessor<WaveViewData> whenReady) {
wavelets.updateData(
parseConvWaveletData(
convConnectResponse, convSnapshot,
getDocumentRegistry(), diffMap));
if (useUdw) {
wavelets.updateData(
parseUdwData(
udwData.getConnectResponse(),
udwData.getSnapshot(),
getDocumentRegistry()));
}
Document.get().getElementById(WAVEPANEL_PLACEHOLDER).setInnerText("");
waveData = createWaveViewData();
whenReady.use(waveData);